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