[system] / trunk / pg / macros / contextPolynomialFactors.pl Repository: Repository Listing bbplugincoursesdistsnplrochestersystemwww # Diff of /trunk/pg/macros/contextPolynomialFactors.pl

Revision 6217 Revision 6218
1################################################################################ 1################################################################################
2# WeBWorK Online Homework Delivery System 2# WeBWorK Online Homework Delivery System
4# \$CVSHeader: pg/macros/contextPolynomialFactors.pl,v 1.1 2010/03/31 21:01:14 dpvc Exp \$ 4# \$CVSHeader: pg/macros/contextPolynomialFactors.pl,v 1.2 2010/03/31 21:45:42 dpvc Exp \$
5# 5#
6# This program is free software; you can redistribute it and/or modify it under 6# This program is free software; you can redistribute it and/or modify it under
8# Free Software Foundation; either version 2, or (at your option) any later 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. 9# version, or (b) the "Artistic License" which comes with this package.
53product or factors or only on a single factor at at time. These are 53product or factors or only on a single factor at at time. These are
54strictDivision and strictPowers. By default, strictDivisions is 0, so 54strictDivision and strictPowers. By default, strictDivisions is 0, so
55(x*(x+1))/3 is allowed, while strictPowers is 1, so (x*(x+1))^3 is not 55(x*(x+1))/3 is allowed, while strictPowers is 1, so (x*(x+1))^3 is not
56(it must be written x^3*(x+1)^3). 56(it must be written x^3*(x+1)^3).
57 57
58Finally, there is also a strict limited context that does not allow 58Finally, there is also a strict context that does not allow
59operations even within the coefficients. Select it using: 59operations even within the coefficients. Select it using:
60 60
61 Context("PolynomialFactors-Strict"); 61 Context("PolynomialFactors-Strict");
62 62
63In addition to disallowing operations within the coefficients, this 63In addition to disallowing operations within the coefficients, this
107 107
108package PolynomialFactors::BOP::multiply; 108package PolynomialFactors::BOP::multiply;
109our @ISA = qw(LimitedPolynomial::BOP::multiply); 109our @ISA = qw(LimitedPolynomial::BOP::multiply);
110 110
111sub checkPolynomial { 111sub checkPolynomial {
112 my \$self = shift;
113 my (\$l,\$r) = (\$self->{lop},\$self->{rop}); 112 my \$self = shift; my (\$l,\$r) = (\$self->{lop},\$self->{rop});
114 my \$lOK = (LimitedPolynomial::isConstant(\$l) || \$l->{isPower} || 113 my \$lOK = (LimitedPolynomial::isConstant(\$l) || \$l->{isPower} ||
115 \$l->class eq 'Variable' || (\$l->{isPoly} && \$l->{isPoly} == 2)); 114 \$l->class eq 'Variable' || (\$l->{isPoly} && \$l->{isPoly} == 2));
116 my \$rOK = (\$r->{isPower} || \$r->class eq 'Variable'); 115 my \$rOK = (\$r->{isPower} || \$r->class eq 'Variable');
117 return \$self->checkExponents if \$lOK and \$rOK; 116 return \$self->checkExponents if \$lOK and \$rOK;
118 \$self->Error("Coefficients must come before variables or factors") 117 \$self->Error("Coefficients must come before variables or factors")
134 \$self->Error("Each factor can appear only once (combine like factors)") unless \$factor eq "0"; 133 \$self->Error("Each factor can appear only once (combine like factors)") unless \$factor eq "0";
135 \$self->Error("Only one constant coefficient or negation is allowed (combine them)"); 134 \$self->Error("Only one constant coefficient or negation is allowed (combine them)");
136 } 135 }
137 \$self->{factors}{\$factor} = 1; 136 \$self->{factors}{\$factor} = 1;
138 } 137 }
138 delete \$r->{factors};
139 \$self->{isPoly} = 4; # product of factors 139 \$self->{isPoly} = 4; # product of factors
140 return 1; 140 return 1;
141} 141}
142 142
143sub checkStrict { 143sub checkStrict {
149 149
150package PolynomialFactors::BOP::divide; 150package PolynomialFactors::BOP::divide;
151our @ISA = qw(LimitedPolynomial::BOP::divide); 151our @ISA = qw(LimitedPolynomial::BOP::divide);
152 152
153sub checkPolynomial { 153sub checkPolynomial {
154 my \$self = shift;
155 my (\$l,\$r) = (\$self->{lop},\$self->{rop}); 154 my \$self = shift; my (\$l,\$r) = (\$self->{lop},\$self->{rop});
156 \$self->Error("In a polynomial, you can only divide by numbers") 155 \$self->Error("In a polynomial, you can only divide by numbers")
157 unless LimitedPolynomial::isConstant(\$r); 156 unless LimitedPolynomial::isConstant(\$r);
158 if (\$l->{isPoly} && \$l->{isPoly} != 2) { 157 if (\$l->{isPoly} && \$l->{isPoly} != 2) {
159 \$self->Error("You can only divide a single term or factor by a number") 158 \$self->Error("You can only divide a single term or factor by a number")
160 if \$l->{isPoly} == 3 || (\$self->context->flag("strictDivision") && \$self->{isPoly} != 1); 159 if \$l->{isPoly} == 3 || (\$self->context->flag("strictDivision") && \$l->{isPoly} != 1);
161 PolynomialFactors::markFactor(\$l); 160 PolynomialFactors::markOpFactor(\$self,\$l);
162 \$self->Error("Only one constant multiple or fraction is allowed (combine them)") 161 \$self->Error("Only one constant multiple or fraction is allowed (combine them)")
163 if \$l->{factors}{0} && \$self->context->flag("singleFactors"); 162 if \$self->{factors}{0} && \$self->context->flag("singleFactors");
164 \$self->{factors} = \$l->{factors}; delete \$l->{factors};
165 \$self->{factors}{0} = 1; # mark as constant multiple; 163 \$self->{factors}{0} = 1; # mark as constant multiple;
166 \$self->{isPoly} = 3; # factor over a number 164 \$self->{isPoly} = 3; # factor over a number
167 } else { 165 } else {
168 \$self->{isPoly} = \$l->{isPoly}; 166 \$self->{isPoly} = \$l->{isPoly};
169 \$self->{powers} = \$l->{powers}; delete \$l->{powers}; 167 \$self->{powers} = \$l->{powers}; delete \$l->{powers};
176 174
177package PolynomialFactors::BOP::power; 175package PolynomialFactors::BOP::power;
178our @ISA = qw(LimitedPolynomial::BOP::power); 176our @ISA = qw(LimitedPolynomial::BOP::power);
179 177
180sub checkPolynomial { 178sub checkPolynomial {
181 my \$self = shift;
182 my (\$l,\$r) = (\$self->{lop},\$self->{rop}); 179 my \$self = shift; my (\$l,\$r) = (\$self->{lop},\$self->{rop});
183 \$self->Error("Exponents must be constant in a polynomial") 180 \$self->Error("Exponents must be constant in a polynomial")
184 unless LimitedPolynomial::isConstant(\$r); 181 unless LimitedPolynomial::isConstant(\$r);
185 my \$n = Parser::Evaluate(\$r); 182 my \$n = Parser::Evaluate(\$r);
186 \$r->Error(\$\$Value::context->{error}{message}) if \$\$Value::context->{error}{flag}; 183 \$r->Error(\$\$Value::context->{error}{message}) if \$\$Value::context->{error}{flag};
187 \$n = \$n->value; 184 \$n = \$n->value;
188 \$self->Error("Exponents must be positive integers in a polynomial") 185 \$self->Error("Exponents must be positive integers in a polynomial")
189 unless \$n > 0 && \$n == int(\$n); 186 unless \$n > 0 && \$n == int(\$n);
190 if (\$l->{isPoly}) { 187 if (\$l->{isPoly}) {
191 \$self->Error("You can only raise a single term or factor to a power") 188 \$self->Error("You can only raise a single term or factor to a power")
192 if \$l->{isPoly} > 2 && \$self->context->flag("strictPowers"); 189 if \$l->{isPoly} > 2 && \$self->context->flag("strictPowers");
193 PolynomialFactors::markFactor(\$l); 190 PolynomialFactors::markOpFactor(\$self,\$l);
194 \$self->{factors} = \$l->{factors}; delete \$l->{factors};
195 \$self->{isPoly} = 5; # factor to a power 191 \$self->{isPoly} = 5; # factor to a power
196 } else { 192 } else {
197 LimitedPolynomial::markPowers(\$l); 193 LimitedPolynomial::markPowers(\$l);
198 \$self->{exponents} = \$l->{exponents}; delete \$l->{exponents}; 194 \$self->{exponents} = \$l->{exponents}; delete \$l->{exponents};
199 foreach my \$i (@{\$self->{exponents}}) {\$i = \$n if \$i} 195 foreach my \$i (@{\$self->{exponents}}) {\$i = \$n if \$i}
214 210
215sub checkPolynomial { 211sub checkPolynomial {
216 my \$self = shift; my \$op = \$self->{op}; 212 my \$self = shift; my \$op = \$self->{op};
217 if (\$op->{isPoly} && \$self->context->flag("singleFactors")) { 213 if (\$op->{isPoly} && \$self->context->flag("singleFactors")) {
218 \$self->Error("Double negatives are not allowed") if \$op->{isPoly} == 2; 214 \$self->Error("Double negatives are not allowed") if \$op->{isPoly} == 2;
219 \$self->Error("Only one factor or constant can be negated") 215 \$self->Error("Only one factor or constant can be negated") if \$op->{isPoly} == 4;
220 if \$op->{isPoly} != 1 && \$op->{isPoly} != 5;
221 } 216 }
222 PolynomialFactors::markFactor(\$op); 217 PolynomialFactors::markOpFactor(\$self,\$op);
223 \$self->{factors} = \$op->{factors}; delete \$op->{factors};
224 \$self->{factors}{0} = 1; # mark as constant multiple 218 \$self->{factors}{0} = 1; # mark as constant multiple
225 return 1; 219 return 1;
226} 220}
227 221
228############################################## 222##############################################
241 } elsif (\$self->{isPoly} && \$self->{isPoly} == 1) { 235 } elsif (\$self->{isPoly} && \$self->{isPoly} == 1) {
242 \$self->{factors}{\$self->string} = 1; 236 \$self->{factors}{\$self->string} = 1;
243 } elsif (\$self->{isPower}) { 237 } elsif (\$self->{isPower}) {
244 \$self->{factors}{\$self->{lop}->string} = 1; 238 \$self->{factors}{\$self->{lop}->string} = 1;
245 } 239 }
240}
241
242sub markOpFactor {
243 my \$self = shift; my \$op = shift;
244 markFactor(\$op);
245 \$self->{factors} = \$op->{factors};
246 delete \$op->{factors};
246} 247}
247 248
248sub Init { 249sub Init {
249 # 250 #
250 # Build the new context that calls the 251 # Build the new context that calls the

Legend:
 Removed from v.6217 changed lines Added in v.6218