Annotation of loncom/homework/math_parser/QVector.pm, revision 1.2
1.1 damieng 1: # The LearningOnline Network with CAPA - LON-CAPA
2: # QVector
3: #
1.2 ! raeburn 4: # $Id: QVector.pm,v 1.2 2023/03/13 18:30:00 raeburn Exp $
! 5: #
1.1 damieng 6: # Copyright (C) 2014 Michigan State University Board of Trustees
7: #
8: # This program is free software: you can redistribute it and/or modify
9: # it under the terms of the GNU General Public License as published by
10: # the Free Software Foundation, either version 3 of the License, or
11: # (at your option) any later version.
12: #
13: # This program is distributed in the hope that it will be useful,
14: # but WITHOUT ANY WARRANTY; without even the implied warranty of
15: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: # GNU General Public License for more details.
17: #
18: # You should have received a copy of the GNU General Public License
19: # along with this program. If not, see <http://www.gnu.org/licenses/>.
20: #
21:
22: ##
23: # A vector of quantities
24: ##
25: package Apache::math_parser::QVector;
26:
27: use strict;
28: use warnings;
29: use utf8;
30:
31: use aliased 'Apache::math_parser::CalcException';
32: use aliased 'Apache::math_parser::Quantity';
33: use aliased 'Apache::math_parser::QVector';
34:
35: use overload
36: '""' => \&toString,
37: '+' => \&qadd,
38: '-' => \&qsub,
39: '*' => \&qmult,
40: '/' => \&qdiv,
41: '^' => \&qpow;
42:
43: ##
44: # Constructor
45: # @param {Quantity[]} quantities
46: ##
47: sub new {
48: my $class = shift;
49: my $self = {
50: _quantities => shift,
51: };
52: bless $self, $class;
53: return $self;
54: }
55:
56: # Attribute helpers
57:
58: ##
59: # The components of the vector.
60: # @returns {Quantity[]}
61: ##
62: sub quantities {
63: my $self = shift;
64: return $self->{_quantities};
65: }
66:
67:
68: ##
69: # Returns a readable view of the object
70: # @returns {string}
71: ##
72: sub toString {
73: my ( $self ) = @_;
74: my $s = "[";
75: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
76: $s .= $self->quantities->[$i]->toString();
77: if ($i != scalar(@{$self->quantities}) - 1) {
78: $s .= "; ";
79: }
80: }
81: $s .= "]";
82: return $s;
83: }
84:
85: ##
86: # Equality test
87: # @param {QVector} v
88: # @optional {string|float} tolerance
89: # @returns {boolean}
90: ##
91: sub equals {
92: my ( $self, $v, $tolerance ) = @_;
93: if (!$v->isa(QVector)) {
94: return 0;
95: }
96: if (scalar(@{$self->quantities}) != scalar(@{$v->quantities})) {
97: return 0;
98: }
99: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
100: if (!$self->quantities->[$i]->equals($v->quantities->[$i], $tolerance)) {
101: return 0;
102: }
103: }
104: return 1;
105: }
106:
107: ##
108: # Compare this vector with another one, and returns a code.
109: # Returns Quantity->WRONG_TYPE if the parameter is not a QVector.
110: # @param {Quantity|QVector|QMatrix|QSet|QInterval} v
111: # @optional {string|float} tolerance
112: # @returns {int} Quantity->WRONG_TYPE|WRONG_DIMENSIONS|MISSING_UNITS|ADDED_UNITS|WRONG_UNITS|WRONG_VALUE|IDENTICAL
113: ##
114: sub compare {
115: my ( $self, $v, $tolerance ) = @_;
116: if (!$v->isa(QVector)) {
117: return Quantity->WRONG_TYPE;
118: }
119: if (scalar(@{$self->quantities}) != scalar(@{$v->quantities})) {
120: return Quantity->WRONG_DIMENSIONS;
121: }
122: my @codes = ();
123: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
124: push(@codes, $self->quantities->[$i]->compare($v->quantities->[$i], $tolerance));
125: }
126: my @test_order = (Quantity->WRONG_TYPE, Quantity->WRONG_DIMENSIONS, Quantity->MISSING_UNITS, Quantity->ADDED_UNITS,
127: Quantity->WRONG_UNITS, Quantity->WRONG_VALUE);
128: foreach my $test (@test_order) {
129: foreach my $code (@codes) {
130: if ($code == $test) {
131: return $test;
132: }
133: }
134: }
135: return Quantity->IDENTICAL;
136: }
137:
138: ##
139: # Interprets this vector as an unordered list of quantities, compares it with another one, and returns a code.
140: # Returns Quantity->WRONG_TYPE if the parameter is not a QVector.
141: # @param {Quantity|QVector|QMatrix|QSet|QInterval} v
142: # @optional {string|float} tolerance
143: # @returns {int} Quantity->WRONG_TYPE|WRONG_DIMENSIONS|MISSING_UNITS|ADDED_UNITS|WRONG_UNITS|WRONG_VALUE|IDENTICAL
144: ##
145: sub compare_unordered {
146: my ( $self, $v, $tolerance ) = @_;
147: if (!$v->isa(QVector)) {
148: return Quantity->WRONG_TYPE;
149: }
150: if (scalar(@{$self->quantities}) != scalar(@{$v->quantities})) {
151: return Quantity->WRONG_DIMENSIONS;
152: }
153: my @quantities_1 = sort {$a <=> $b} @{$self->quantities};
154: my $v1 = QVector->new(\@quantities_1);
155: my @quantities_2 = sort {$a <=> $b} @{$v->quantities};
156: my $v2 = QVector->new(\@quantities_2);
157: return($v1->compare($v2, $tolerance));
158: }
159:
160: ##
161: # Addition
162: # @param {QVector} v
163: # @returns {QVector}
164: ##
165: sub qadd {
166: my ( $self, $v ) = @_;
167: if (!$v->isa(QVector)) {
168: die CalcException->new("Vector addition: second member is not a vector.");
169: }
170: if (scalar(@{$self->quantities}) != scalar(@{$v->quantities})) {
171: die CalcException->new("Vector addition: the vectors have different sizes.");
172: }
173: my @t = (); # array of Quantity
174: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
175: $t[$i] = $self->quantities->[$i] + $v->quantities->[$i];
176: }
177: return QVector->new(\@t);
178: }
179:
180: ##
181: # Substraction
182: # @param {QVector} v
183: # @returns {QVector}
184: ##
185: sub qsub {
186: my ( $self, $v ) = @_;
187: if (!$v->isa(QVector)) {
188: die CalcException->new("Vector substraction: second member is not a vector.");
189: }
190: if (scalar(@{$self->quantities}) != scalar(@{$v->quantities})) {
191: die CalcException->new("Vector substraction: the vectors have different sizes.");
192: }
193: my @t = (); # array of Quantity
194: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
195: $t[$i] = $self->quantities->[$i] - $v->quantities->[$i];
196: }
197: return QVector->new(\@t);
198: }
199:
200: ##
201: # Negation
202: # @returns {QVector}
203: ##
204: sub qneg {
205: my ( $self ) = @_;
206: my @t = (); # array of Quantity
207: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
208: $t[$i] = $self->quantities->[$i]->qneg();
209: }
210: return QVector->new(\@t);
211: }
212:
213: ##
214: # Multiplication by a scalar, or element-by-element multiplication by a vector
215: # @param {Quantity|QVector} qv
216: # @returns {QVector}
217: ##
218: sub qmult {
219: my ( $self, $qv ) = @_;
220: if (!$qv->isa(Quantity) && !$qv->isa(QVector)) {
221: die CalcException->new("Vector multiplication: second member is not a quantity or a vector.");
222: }
223: my @t = (); # array of Quantity
224: if ($qv->isa(Quantity)) {
225: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
226: $t[$i] = $self->quantities->[$i] * $qv;
227: }
228: } else {
229: if (scalar(@{$self->quantities}) != scalar(@{$qv->quantities})) {
230: die CalcException->new("Vector element-by-element multiplication: the vectors have different sizes.");
231: }
232: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
233: $t[$i] = $self->quantities->[$i]->qmult($qv->quantities->[$i]);
234: }
235: }
236: return QVector->new(\@t);
237: }
238:
239: ##
240: # Division
241: # @param {Quantity|QVector} qv
242: # @returns {QVector}
243: ##
244: sub qdiv {
245: my ( $self, $qv ) = @_;
246: if (!$qv->isa(Quantity) && !$qv->isa(QVector)) {
247: die CalcException->new("Vector division: second member is not a quantity or a vector.");
248: }
249: my @t = (); # array of Quantity
250: if ($qv->isa(Quantity)) {
251: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
252: $t[$i] = $self->quantities->[$i] / $qv;
253: }
254: } else {
255: if (scalar(@{$self->quantities}) != scalar(@{$qv->quantities})) {
256: die CalcException->new("Vector element-by-element division: the vectors have different sizes.");
257: }
258: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
259: $t[$i] = $self->quantities->[$i]->qdiv($qv->quantities->[$i]);
260: }
261: }
262: return QVector->new(\@t);
263: }
264:
265: ##
266: # Power by a scalar
267: # @param {Quantity} q
268: # @returns {QVector}
269: ##
270: sub qpow {
271: my ( $self, $q ) = @_;
272: if (!$q->isa(Quantity)) {
273: die CalcException->new("Vector power: second member is not a quantity.");
274: }
275: $q->noUnits("Power");
276: my @t = (); # array of Quantity
277: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
278: $t[$i] = $self->quantities->[$i] ^ $q;
279: }
280: return QVector->new(\@t);
281: }
282:
283: ##
284: # Dot product
285: # @param {QVector} v
286: # @returns {Quantity}
287: ##
288: sub qdot {
289: my ( $self, $v ) = @_;
290: if (!$v->isa(QVector)) {
291: die CalcException->new("Vector dot product: second member is not a vector.");
292: }
293: if (scalar(@{$self->quantities}) != scalar(@{$v->quantities})) {
294: die CalcException->new("Vector dot product: the vectors have different sizes.");
295: }
296: my $q = Quantity->new(0);
297: for (my $i=0; $i < scalar(@{$self->quantities}); $i++) {
298: $q = $q + $self->quantities->[$i]->qmult($v->quantities->[$i]);
299: }
300: return $q;
301: }
302:
303: ##
304: # Equals
305: # @param {Quantity|QVector|QMatrix|QSet|QInterval} v
306: # @optional {string|float} tolerance
307: # @returns {Quantity}
308: ##
309: sub qeq {
310: my ( $self, $v, $tolerance ) = @_;
311: my $q = $self->equals($v, $tolerance);
312: return Quantity->new($q);
313: }
314:
315: 1;
316: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>