File:  [LON-CAPA] / loncom / homework / math_parser / Quantity.pm
Revision 1.2: download - view: text, annotated - select for diffs
Mon Mar 13 22:31:22 2023 UTC (14 months, 3 weeks ago) by raeburn
Branches: MAIN
CVS tags: version_2_12_X, version_2_11_4_msu, HEAD
- Add $Id$ line in comments for display of version.

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

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