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>