Annotation of loncom/homework/math_parser/Quantity.pm, revision 1.1

1.1     ! damieng     1: # The LearningOnline Network with CAPA - LON-CAPA
        !             2: # Quantity
        !             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 quantity (value and units)
        !            22: ##
        !            23: package Apache::math_parser::Quantity;
        !            24: 
        !            25: use strict;
        !            26: use warnings;
        !            27: use utf8;
        !            28: 
        !            29: use POSIX;
        !            30: use Math::Complex; # must be after POSIX for redefinition of log10
        !            31: 
        !            32: use aliased 'Apache::math_parser::CalcException';
        !            33: use aliased 'Apache::math_parser::Quantity';
        !            34: use aliased 'Apache::math_parser::QVector';
        !            35: use aliased 'Apache::math_parser::QMatrix';
        !            36: use aliased 'Apache::math_parser::QSet';
        !            37: use aliased 'Apache::math_parser::QInterval';
        !            38: use aliased 'Apache::math_parser::QIntervalUnion';
        !            39: 
        !            40: use overload
        !            41:     '""' => \&toString,
        !            42:     '+' => \&qadd,
        !            43:     '-' => \&qsub,
        !            44:     '*' => \&qmult,
        !            45:     '/' => \&qdiv,
        !            46:     '^' => \&qpow,
        !            47:     '<' => \&qlt,
        !            48:     '<=' => \&qle,
        !            49:     '>' => \&qgt,
        !            50:     '>=' => \&qge,
        !            51:     '<=>' => \&perl_compare;
        !            52: 
        !            53: # compare() return codes:
        !            54: use enum qw(IDENTICAL WRONG_TYPE WRONG_DIMENSIONS MISSING_UNITS ADDED_UNITS WRONG_UNITS WRONG_VALUE WRONG_ENDPOINT);
        !            55: 
        !            56: 
        !            57: ##
        !            58: # Constructor
        !            59: # @param {complex} value
        !            60: # @optional {Object.<string, integer>} units - hash: unit name -> exponent for each SI unit
        !            61: ##
        !            62: sub new {
        !            63:     my $class = shift;
        !            64:     my $self = {
        !            65:         _value => shift,
        !            66:         _units => shift,
        !            67:     };
        !            68:     if ("".$self->{_value} eq "i") {
        !            69:         $self->{_value} = i;
        !            70:     } elsif ("".$self->{_value} eq "inf") {
        !            71:         $self->{_value} = 9**9**9;
        !            72:     }
        !            73:     if (!defined $self->{_units}) {
        !            74:         $self->{_units} = {
        !            75:             s => 0,
        !            76:             m => 0,
        !            77:             kg => 0,
        !            78:             K => 0,
        !            79:             A => 0,
        !            80:             mol => 0,
        !            81:             cd => 0
        !            82:         };
        !            83:     } else {
        !            84:         foreach my $unit ('s', 'm', 'kg', 'K', 'A', 'mol', 'cd') {
        !            85:             if (!defined $self->{_units}->{$unit}) {
        !            86:                 $self->{_units}->{$unit} = 0;
        !            87:             }
        !            88:         }
        !            89:     }
        !            90:     bless $self, $class;
        !            91:     return $self;
        !            92: }
        !            93: 
        !            94: # Attribute helpers
        !            95: 
        !            96: ##
        !            97: # Value.
        !            98: # @returns {Complex}
        !            99: ##
        !           100: sub value {
        !           101:     my $self = shift;
        !           102:     return $self->{_value};
        !           103: }
        !           104: 
        !           105: 
        !           106: ##
        !           107: # Units
        !           108: # @returns {Object.<string, integer>} hash: unit name -> exponent for each SI unit
        !           109: ##
        !           110: sub units {
        !           111:     my $self = shift;
        !           112:     return $self->{_units};
        !           113: }
        !           114: 
        !           115: 
        !           116: ##
        !           117: # Returns a readable view of the object
        !           118: # @returns {string}
        !           119: ##
        !           120: sub toString {
        !           121:     my ( $self ) = @_;
        !           122:     my $s;
        !           123:     # complex display in polar notation can be confused with vectors
        !           124:     # normally we should just have to call 	Math::Complex::display_format('cartesian');
        !           125:     # actually, it's supposed to be the default...
        !           126:     # but this is not working, so...
        !           127:     if ($self->value =~ /\[/) {
        !           128:         my $v = $self->value;
        !           129:         $v->display_format('cartesian');
        !           130:         $s = "".$v;
        !           131:     } else {
        !           132:         $s = $self->value;
        !           133:     }
        !           134:     foreach my $unit (keys %{$self->units}) {
        !           135:         my $e = $self->units->{$unit};
        !           136:         if ($e != 0) {
        !           137:             $s .= " ".$unit;
        !           138:             if ($e != 1) {
        !           139:                 $s .= "^".$e;
        !           140:             }
        !           141:         }
        !           142:     }
        !           143:     return $s;
        !           144: }
        !           145: 
        !           146: ##
        !           147: # Equality test
        !           148: # @param {Quantity}
        !           149: # @optional {string|float} tolerance
        !           150: # @returns {boolean}
        !           151: ##
        !           152: sub equals {
        !           153:     my ( $self, $q, $tolerance ) = @_;
        !           154:     if (!$q->isa(Quantity)) {
        !           155:         return 0;
        !           156:     }
        !           157:     if (!defined $tolerance) {
        !           158:         $tolerance = 0;
        !           159:     }
        !           160:     if ($tolerance =~ /%/) {
        !           161:         my $perc = $tolerance;
        !           162:         $perc =~ s/%//;
        !           163:         $perc /= 100;
        !           164:         if (abs($self->value - $q->value) > abs($self->value * $perc)) {
        !           165:             return 0;
        !           166:         }
        !           167:     } else {
        !           168:         if (abs($self->value - $q->value) > $tolerance) {
        !           169:             return 0;
        !           170:         }
        !           171:     }
        !           172:     my %units = %{$self->units};
        !           173:     foreach my $unit (keys %units) {
        !           174:         if ($units{$unit} != $q->units->{$unit}) {
        !           175:             return 0;
        !           176:         }
        !           177:     }
        !           178:     return 1;
        !           179: }
        !           180: 
        !           181: ##
        !           182: # Compare this quantity with another one, and returns a code.
        !           183: # Returns Quantity->WRONG_TYPE if the parameter is not a Quantity.
        !           184: # @param {Quantity|QVector|QMatrix|QSet|QInterval} q
        !           185: # @optional {string|float} tolerance
        !           186: # @returns {int} WRONG_TYPE|MISSING_UNITS|ADDED_UNITS|WRONG_UNITS|WRONG_VALUE|IDENTICAL
        !           187: ##
        !           188: sub compare {
        !           189:     my ( $self, $q, $tolerance ) = @_;
        !           190:     if (!$q->isa(Quantity)) {
        !           191:         return WRONG_TYPE;
        !           192:     }
        !           193:     if (!defined $tolerance) {
        !           194:         $tolerance = 0;
        !           195:     }
        !           196:     my %units = %{$self->units};
        !           197:     my $this_has_units = 0;
        !           198:     my $other_has_units = 0;
        !           199:     my $wrong_units = 0;
        !           200:     foreach my $unit (keys %units) {
        !           201:         if ($units{$unit} != 0) {
        !           202:             $this_has_units = 1;
        !           203:         }
        !           204:         if ($q->units->{$unit} != 0) {
        !           205:             $other_has_units = 1;
        !           206:         }
        !           207:         if ($units{$unit} != $q->units->{$unit}) {
        !           208:             $wrong_units = 1;
        !           209:         }
        !           210:     }
        !           211:     if ($this_has_units && !$other_has_units) {
        !           212:         return MISSING_UNITS;
        !           213:     } elsif (!$this_has_units && $other_has_units) {
        !           214:         return ADDED_UNITS;
        !           215:     }
        !           216:     if ($wrong_units) {
        !           217:         return WRONG_UNITS;
        !           218:     }
        !           219:     if ($tolerance =~ /%/) {
        !           220:         my $perc = $tolerance;
        !           221:         $perc =~ s/%//;
        !           222:         $perc /= 100;
        !           223:         if (abs($self->value - $q->value) > abs($self->value * $perc)) {
        !           224:             return WRONG_VALUE;
        !           225:         }
        !           226:     } else {
        !           227:         if (abs($self->value - $q->value) > $tolerance) {
        !           228:             return WRONG_VALUE;
        !           229:         }
        !           230:     }
        !           231:     return IDENTICAL;
        !           232: }
        !           233: 
        !           234: ##
        !           235: # <=> operator.
        !           236: # Compare this quantity with another one, and returns -1, 0 or 1.
        !           237: # @param {Quantity} q
        !           238: # @returns {int}
        !           239: ##
        !           240: sub perl_compare {
        !           241:     my ( $self, $q ) = @_;
        !           242:     if (!$q->isa(Quantity)) {
        !           243:         die CalcException->new("Quantity comparison: second member is not a quantity.");
        !           244:     }
        !           245:     $self->unitsMatch($q, 'perl_compare');
        !           246:     return($self->value <=> $q->value);
        !           247: }
        !           248: 
        !           249: ##
        !           250: # Not equal
        !           251: # @param {Quantity} q
        !           252: # @optional {string|float} tolerance
        !           253: # @returns {boolean}
        !           254: ##
        !           255: sub ne {
        !           256:     my ( $self, $q, $tolerance ) = @_;
        !           257:     if ($self->equals($q, $tolerance)) {
        !           258:         return(0);
        !           259:     } else {
        !           260:         return(1);
        !           261:     }
        !           262: }
        !           263: 
        !           264: ##
        !           265: # Less than
        !           266: # @param {Quantity} q
        !           267: # @returns {boolean}
        !           268: ##
        !           269: sub lt {
        !           270:     my ( $self, $q ) = @_;
        !           271:     if (!$q->isa(Quantity)) {
        !           272:         die CalcException->new("Quantity smaller than: second member is not a quantity.");
        !           273:     }
        !           274:     $self->unitsMatch($q, 'lt');
        !           275:     if ($self->value < $q->value) {
        !           276:         return(1);
        !           277:     } else {
        !           278:         return(0);
        !           279:     }
        !           280: }
        !           281: 
        !           282: ##
        !           283: # Less than or equal
        !           284: # @param {Quantity} q
        !           285: # @returns {boolean}
        !           286: ##
        !           287: sub le {
        !           288:     my ( $self, $q ) = @_;
        !           289:     if (!$q->isa(Quantity)) {
        !           290:         die CalcException->new("Quantity smaller or equal: second member is not a quantity.");
        !           291:     }
        !           292:     $self->unitsMatch($q, 'le');
        !           293:     if ($self->value <= $q->value) {
        !           294:         return(1);
        !           295:     } else {
        !           296:         return(0);
        !           297:     }
        !           298: }
        !           299: 
        !           300: ##
        !           301: # Greater than
        !           302: # @param {Quantity} q
        !           303: # @returns {boolean}
        !           304: ##
        !           305: sub gt {
        !           306:     my ( $self, $q ) = @_;
        !           307:     if (!$q->isa(Quantity)) {
        !           308:         die CalcException->new("Quantity greater than: second member is not a quantity.");
        !           309:     }
        !           310:     $self->unitsMatch($q, 'gt');
        !           311:     if ($self->value > $q->value) {
        !           312:         return(1);
        !           313:     } else {
        !           314:         return(0);
        !           315:     }
        !           316: }
        !           317: 
        !           318: ##
        !           319: # Greater than or equal
        !           320: # @param {Quantity} q
        !           321: # @returns {boolean}
        !           322: ##
        !           323: sub ge {
        !           324:     my ( $self, $q ) = @_;
        !           325:     if (!$q->isa(Quantity)) {
        !           326:         die CalcException->new("Quantity greater or equal: second member is not a quantity.");
        !           327:     }
        !           328:     $self->unitsMatch($q, 'ge');
        !           329:     if ($self->value >= $q->value) {
        !           330:         return(1);
        !           331:     } else {
        !           332:         return(0);
        !           333:     }
        !           334: }
        !           335: 
        !           336: ##
        !           337: # Clone this object
        !           338: # @returns {Quantity}
        !           339: ##
        !           340: sub clone {
        !           341:     my ( $self ) = @_;
        !           342:     my %units = %{$self->units};
        !           343:     return Quantity->new($self->value, \%units);
        !           344: }
        !           345: 
        !           346: ##
        !           347: # Addition
        !           348: # @param {Quantity} q
        !           349: # @returns {Quantity}
        !           350: ##
        !           351: sub qadd {
        !           352:     my ( $self, $q ) = @_;
        !           353:     if (!$q->isa(Quantity)) {
        !           354:         die CalcException->new("Quantity addition: second member is not a quantity.");
        !           355:     }
        !           356:     my $v = $self->value + $q->value;
        !           357:     $self->unitsMatch($q, 'addition');
        !           358:     return Quantity->new($v, $self->units);
        !           359: }
        !           360: 
        !           361: ##
        !           362: # Substraction
        !           363: # @param {Quantity} q
        !           364: # @returns {Quantity}
        !           365: ##
        !           366: sub qsub {
        !           367:     my ( $self, $q ) = @_;
        !           368:     if (!$q->isa(Quantity)) {
        !           369:         die CalcException->new("Quantity substraction: second member is not a quantity.");
        !           370:     }
        !           371:     my $v = $self->value - $q->value;
        !           372:     $self->unitsMatch($q, 'substraction');
        !           373:     return Quantity->new($v, $self->units);
        !           374: }
        !           375: 
        !           376: ##
        !           377: # Negation
        !           378: # @returns {Quantity}
        !           379: ##
        !           380: sub qneg {
        !           381:     my ( $self ) = @_;
        !           382:     my $v = - $self->value;
        !           383:     my %units = %{$self->units};
        !           384:     return Quantity->new($v, \%units);
        !           385: }
        !           386: 
        !           387: ##
        !           388: # Multiplication
        !           389: # @param {Quantity|QVector|QMatrix|QSet|QInterval|QIntervalUnion} qv
        !           390: # @returns {Quantity|QVector|QMatrix|QSet|QInterval|QIntervalUnion}
        !           391: ##
        !           392: sub qmult {
        !           393:     my ( $self, $qv ) = @_;
        !           394:     if (!$qv->isa(Quantity) && !$qv->isa(QVector) && !$qv->isa(QMatrix) &&
        !           395:             !$qv->isa(QSet) && !$qv->isa(QInterval) && !$qv->isa(QIntervalUnion)) {
        !           396:         die CalcException->new("Cannot multiply with something that is not a quantity, vector, matrix, set, or interval.");
        !           397:     }
        !           398:     if ($qv->isa(QVector) || $qv->isa(QMatrix) || $qv->isa(QSet) || $qv->isa(QInterval) || $qv->isa(QIntervalUnion)) {
        !           399:         return($qv->qmult($self));
        !           400:     }
        !           401:     my $q = $qv;
        !           402:     my $v = $self->value * $q->value;
        !           403:     my %units = %{$self->units};
        !           404:     foreach my $unit (keys %units) {
        !           405:         $units{$unit} = $units{$unit} + $q->units->{$unit};
        !           406:     }
        !           407:     return Quantity->new($v, \%units);
        !           408: }
        !           409: 
        !           410: ##
        !           411: # Division
        !           412: # @param {Quantity} q
        !           413: # @returns {Quantity}
        !           414: ##
        !           415: sub qdiv {
        !           416:     my ( $self, $q ) = @_;
        !           417:     if (!$q->isa(Quantity)) {
        !           418:         die CalcException->new("Cannot divide by something that is not a quantity.");
        !           419:     }
        !           420:     if ($q->value == 0) {
        !           421:         die CalcException->new("Division by zero.");
        !           422:     }
        !           423:     my $v = $self->value / $q->value;
        !           424:     my %units = %{$self->units};
        !           425:     foreach my $unit (keys %units) {
        !           426:         $units{$unit} = $units{$unit} - $q->units->{$unit};
        !           427:     }
        !           428:     return Quantity->new($v, \%units);
        !           429: }
        !           430: 
        !           431: ##
        !           432: # Power
        !           433: # @param {Quantity} q
        !           434: # @returns {Quantity}
        !           435: ##
        !           436: sub qpow {
        !           437:     my ( $self, $q ) = @_;
        !           438:     if (!$q->isa(Quantity)) {
        !           439:         die CalcException->new("Cannot raise to the power of something that is not a number.");
        !           440:     }
        !           441:     my $v = $self->value ** $q->value;
        !           442:     $q->noUnits("Power");
        !           443:     my %units = %{$self->units};
        !           444:     foreach my $unit (keys %{$q->units}) {
        !           445:         $units{$unit} = $units{$unit} * $q->value;
        !           446:     }
        !           447:     return Quantity->new($v, \%units);
        !           448: }
        !           449: 
        !           450: ##
        !           451: # Factorial
        !           452: # @returns {Quantity}
        !           453: ##
        !           454: sub qfact {
        !           455:     my ( $self ) = @_;
        !           456:     my $v = $self->value;
        !           457:     if ($v < 0) {
        !           458:         die CalcException->new("Factorial of a number smaller than zero.");
        !           459:     }
        !           460:     # should check if integer
        !           461:     my $n = $v;
        !           462:     for (my $i=$n - 1; $i > 1; $i--) {
        !           463:         $v *= $i;
        !           464:     }
        !           465:     return Quantity->new($v, $self->units);
        !           466: }
        !           467: 
        !           468: ##
        !           469: # Square root
        !           470: # @returns {Quantity}
        !           471: ##
        !           472: sub qsqrt {
        !           473:     my ( $self ) = @_;
        !           474:     my $v = sqrt($self->value);
        !           475:     my %units = %{$self->units};
        !           476:     foreach my $unit (keys %units) {
        !           477:         $units{$unit} = $units{$unit} / 2;
        !           478:     }
        !           479:     return Quantity->new($v, \%units);
        !           480: }
        !           481: 
        !           482: ##
        !           483: # Absolute value
        !           484: # @returns {Quantity}
        !           485: ##
        !           486: sub qabs {
        !           487:     my ( $self ) = @_;
        !           488:     my $v = abs($self->value);
        !           489:     my %units = %{$self->units};
        !           490:     return Quantity->new($v, \%units);
        !           491: }
        !           492: 
        !           493: ##
        !           494: # Exponential
        !           495: # @returns {Quantity}
        !           496: ##
        !           497: sub qexp {
        !           498:     my ( $self ) = @_;
        !           499:     $self->noUnits("exp");
        !           500:     return Quantity->new(exp($self->value), $self->units);
        !           501: }
        !           502: 
        !           503: ##
        !           504: # Natural logarithm
        !           505: # @returns {Quantity}
        !           506: ##
        !           507: sub qln {
        !           508:     my ( $self ) = @_;
        !           509:     $self->noUnits("ln");
        !           510:     # this will return a complex if the value is < 0
        !           511:     #if ($self->value < 0) {
        !           512:     #    die CalcException->new("Ln of number < 0");
        !           513:     #}
        !           514:     if ($self->value == 0) {
        !           515:         die CalcException->new("Natural logarithm of zero.");
        !           516:     }
        !           517:     return Quantity->new(log($self->value), $self->units);
        !           518: }
        !           519: 
        !           520: ##
        !           521: # Decimal logarithm
        !           522: # @returns {Quantity}
        !           523: ##
        !           524: sub qlog10 {
        !           525:     my ( $self ) = @_;
        !           526:     $self->noUnits("log10");
        !           527:     # this will return a complex if the value is < 0
        !           528:     #if ($self->value < 0) {
        !           529:     #    die CalcException->new("Log10 of number < 0");
        !           530:     #}
        !           531:     if ($self->value == 0) {
        !           532:         die CalcException->new("Logarithm of zero.");
        !           533:     }
        !           534:     return Quantity->new(log10($self->value), $self->units);
        !           535: }
        !           536: 
        !           537: ##
        !           538: # Modulo
        !           539: # @param {Quantity} q
        !           540: # @returns {Quantity}
        !           541: ##
        !           542: sub qmod {
        !           543:     my ( $self, $q ) = @_;
        !           544:     if (!$q->isa(Quantity)) {
        !           545:         die CalcException->new("Cannot calculate the modulus with respect to something that is not a quantity.");
        !           546:     }
        !           547:     my $v = $self->value % $q->value;
        !           548:     return Quantity->new($v, $self->units);
        !           549: }
        !           550: 
        !           551: ##
        !           552: # Returns -1, 0 or 1 depending on the sign of the value
        !           553: # @returns {Quantity}
        !           554: ##
        !           555: sub qsgn {
        !           556:     my ( $self ) = @_;
        !           557:     my $v;
        !           558:     if ($self->value < 0) {
        !           559:         $v = -1;
        !           560:     } elsif ($self->value > 0) {
        !           561:         $v = 1;
        !           562:     } else {
        !           563:         $v = 0;
        !           564:     }
        !           565:     return Quantity->new($v, $self->units);
        !           566: }
        !           567: 
        !           568: ##
        !           569: # Returns the least integer that is greater than or equal to the value.
        !           570: # @returns {Quantity}
        !           571: ##
        !           572: sub qceil {
        !           573:     my ( $self ) = @_;
        !           574:     my $v = ceil($self->value);
        !           575:     return Quantity->new($v, $self->units);
        !           576: }
        !           577: 
        !           578: ##
        !           579: # Returns the largest integer that is less than or equal to the value.
        !           580: # @returns {Quantity}
        !           581: ##
        !           582: sub qfloor {
        !           583:     my ( $self ) = @_;
        !           584:     my $v = floor($self->value);
        !           585:     return Quantity->new($v, $self->units);
        !           586: }
        !           587: 
        !           588: ##
        !           589: # Sine
        !           590: # @returns {Quantity}
        !           591: ##
        !           592: sub qsin {
        !           593:     my ( $self ) = @_;
        !           594:     $self->noUnits("sin");
        !           595:     return Quantity->new(sin($self->value), $self->units);
        !           596: }
        !           597: 
        !           598: ##
        !           599: # Cosine
        !           600: # @returns {Quantity}
        !           601: ##
        !           602: sub qcos {
        !           603:     my ( $self ) = @_;
        !           604:     $self->noUnits("cos");
        !           605:     return Quantity->new(cos($self->value), $self->units);
        !           606: }
        !           607: 
        !           608: ##
        !           609: # Tangent
        !           610: # @returns {Quantity}
        !           611: ##
        !           612: sub qtan {
        !           613:     my ( $self ) = @_;
        !           614:     $self->noUnits("tan");
        !           615:     return Quantity->new(tan($self->value), $self->units);
        !           616: }
        !           617: 
        !           618: ##
        !           619: # Arcsinus
        !           620: # @returns {Quantity}
        !           621: ##
        !           622: sub qasin {
        !           623:     my ( $self ) = @_;
        !           624:     $self->noUnits("asin");
        !           625:     return Quantity->new(asin($self->value), $self->units);
        !           626: }
        !           627: 
        !           628: ##
        !           629: # Arccosinus
        !           630: # @returns {Quantity}
        !           631: ##
        !           632: sub qacos {
        !           633:     my ( $self ) = @_;
        !           634:     $self->noUnits("acos");
        !           635:     return Quantity->new(acos($self->value), $self->units);
        !           636: }
        !           637: 
        !           638: ##
        !           639: # Arctangent
        !           640: # @returns {Quantity}
        !           641: ##
        !           642: sub qatan {
        !           643:     my ( $self ) = @_;
        !           644:     $self->noUnits("atan");
        !           645:     return Quantity->new(atan($self->value), $self->units);
        !           646: }
        !           647: 
        !           648: ##
        !           649: # Arctangent of self/x in the range -pi to pi
        !           650: # @param {Quantity} x
        !           651: # @returns {Quantity}
        !           652: ##
        !           653: sub qatan2 {
        !           654:     my ( $self, $q ) = @_;
        !           655:     if (!$q->isa(Quantity)) {
        !           656:         die CalcException->new("Cannot calculate atan2 if second argument is not a quantity.");
        !           657:     }
        !           658:     $self->noUnits("atan2");
        !           659:     my $v = atan2($self->value, $q->value);
        !           660:     return Quantity->new($v, $self->units);
        !           661: }
        !           662: 
        !           663: ##
        !           664: # Hyperbolic sinus
        !           665: # @returns {Quantity}
        !           666: ##
        !           667: sub qsinh {
        !           668:     my ( $self ) = @_;
        !           669:     $self->noUnits("sinh");
        !           670:     return Quantity->new(sinh($self->value), $self->units);
        !           671: }
        !           672: 
        !           673: ##
        !           674: # Hyperbolic cosinus
        !           675: # @returns {Quantity}
        !           676: ##
        !           677: sub qcosh {
        !           678:     my ( $self ) = @_;
        !           679:     $self->noUnits("cosh");
        !           680:     return Quantity->new(cosh($self->value), $self->units);
        !           681: }
        !           682: 
        !           683: ##
        !           684: # Hyperbolic tangent
        !           685: # @returns {Quantity}
        !           686: ##
        !           687: sub qtanh {
        !           688:     my ( $self ) = @_;
        !           689:     $self->noUnits("tanh");
        !           690:     return Quantity->new(tanh($self->value), $self->units);
        !           691: }
        !           692: 
        !           693: ##
        !           694: # Hyperbolic arcsinus
        !           695: # @returns {Quantity}
        !           696: ##
        !           697: sub qasinh {
        !           698:     my ( $self ) = @_;
        !           699:     $self->noUnits("asinh");
        !           700:     return Quantity->new(asinh($self->value), $self->units);
        !           701: }
        !           702: 
        !           703: ##
        !           704: # Hyperbolic arccosinus
        !           705: # @returns {Quantity}
        !           706: ##
        !           707: sub qacosh {
        !           708:     my ( $self ) = @_;
        !           709:     $self->noUnits("acosh");
        !           710:     return Quantity->new(acosh($self->value), $self->units);
        !           711: }
        !           712: 
        !           713: ##
        !           714: # Hyperbolic arctangent
        !           715: # @returns {Quantity}
        !           716: ##
        !           717: sub qatanh {
        !           718:     my ( $self ) = @_;
        !           719:     $self->noUnits("atanh");
        !           720:     return Quantity->new(atanh($self->value), $self->units);
        !           721: }
        !           722: 
        !           723: ##
        !           724: # Equals
        !           725: # @param {Quantity|QVector|QMatrix|QSet|QInterval} q
        !           726: # @optional {string|float} tolerance
        !           727: # @returns {Quantity}
        !           728: ##
        !           729: sub qeq {
        !           730:     my ( $self, $q, $tolerance ) = @_;
        !           731:     my $v = $self->equals($q, $tolerance);
        !           732:     return Quantity->new($v);
        !           733: }
        !           734: 
        !           735: ##
        !           736: # Less than
        !           737: # @param {Quantity}
        !           738: # @returns {Quantity}
        !           739: ##
        !           740: sub qlt {
        !           741:     my ( $self, $q ) = @_;
        !           742:     my $v = $self->lt($q);
        !           743:     return Quantity->new($v);
        !           744: }
        !           745: 
        !           746: ##
        !           747: # Less than or equal
        !           748: # @param {Quantity} q
        !           749: # @returns {Quantity}
        !           750: ##
        !           751: sub qle {
        !           752:     my ( $self, $q ) = @_;
        !           753:     my $v = $self->le($q);
        !           754:     return Quantity->new($v);
        !           755: }
        !           756: 
        !           757: ##
        !           758: # Greater than
        !           759: # @param {Quantity} q
        !           760: # @returns {Quantity}
        !           761: ##
        !           762: sub qgt {
        !           763:     my ( $self, $q ) = @_;
        !           764:     my $v = $self->gt($q);
        !           765:     return Quantity->new($v);
        !           766: }
        !           767: 
        !           768: ##
        !           769: # Greater than or equal
        !           770: # @param {Quantity} q
        !           771: # @returns {Quantity}
        !           772: ##
        !           773: sub qge {
        !           774:     my ( $self, $q ) = @_;
        !           775:     my $v = $self->ge($q);
        !           776:     return Quantity->new($v);
        !           777: }
        !           778: 
        !           779: ##
        !           780: # Dies if units do not match.
        !           781: ##
        !           782: sub unitsMatch {
        !           783:     my ( $self, $q, $fct_name ) = @_;
        !           784:     my %units = %{$self->units};
        !           785:     foreach my $unit (keys %units) {
        !           786:         if ($units{$unit} != $q->units->{$unit}) {
        !           787:             die CalcException->new("Units [_1] do not match.", $fct_name);
        !           788:         }
        !           789:     }
        !           790: }
        !           791: 
        !           792: ##
        !           793: # Dies if there are any unit.
        !           794: ##
        !           795: sub noUnits {
        !           796:     my ( $self, $fct_name ) = @_;
        !           797:     my %units = %{$self->units};
        !           798:     foreach my $unit (keys %units) {
        !           799:         if ($units{$unit} != 0) {
        !           800:             die CalcException->new("Cannot calculate [_1] of something with units.", $fct_name);
        !           801:         }
        !           802:     }
        !           803: }
        !           804: 
        !           805: 1;
        !           806: __END__

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>