MayaChemTools

   1 package MathUtil;
   2 #
   3 # $RCSfile: MathUtil.pm,v $
   4 # $Date: 2008/04/19 16:11:01 $
   5 # $Revision: 1.9 $
   6 #
   7 # Author: Manish Sud <msud@san.rr.com>
   8 #
   9 # Copyright (C) 2004-2008 Manish Sud. All rights reserved.
  10 #
  11 # This file is part of MayaChemTools.
  12 #
  13 # MayaChemTools is free software; you can redistribute it and/or modify it under
  14 # the terms of the GNU Lesser General Public License as published by the Free
  15 # Software Foundation; either version 3 of the License, or (at your option) any
  16 # later version.
  17 #
  18 # MayaChemTools is distributed in the hope that it will be useful, but without
  19 # any warranty; without even the implied warranty of merchantability of fitness
  20 # for a particular purpose.  See the GNU Lesser General Public License for more
  21 # details.
  22 #
  23 # You should have received a copy of the GNU Lesser General Public License
  24 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
  25 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
  26 # Boston, MA, 02111-1307, USA.
  27 #
  28 use 5.006;
  29 use strict;
  30 use Exporter;
  31 use Constants;
  32 use Math::Trig ();
  33 use POSIX ();
  34 
  35 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  36 
  37 $VERSION = '1.00';
  38 @ISA = qw(Exporter);
  39 @EXPORT = qw(acos asin atan tan ceil floor log10 min max random round);
  40 @EXPORT_OK = qw();
  41 
  42 %EXPORT_TAGS = (all  => [@EXPORT, @EXPORT_OK]
  43 	       );
  44 
  45 
  46 # Return next largest integer...
  47 sub ceil ($) {
  48   my($Value) = @_;
  49 
  50   return POSIX::ceil($Value);
  51 }
  52 
  53 # Return previous smallest integer...
  54 sub floor ($) {
  55   my($Value) = @_;
  56 
  57   return POSIX::floor($Value);
  58 }
  59 
  60 # Calculate log value using base 10...
  61 sub log10 ($) {
  62   my($Value) = @_;
  63 
  64   return CORE::log($Value)/CORE::log(10);
  65 }
  66 
  67 # Return the smaller of two numbers...
  68 sub min ($$) {
  69   my($Value1, $Value2) = @_;
  70 
  71   return ($Value1 <= $Value2) ? $Value1 : $Value2;
  72 }
  73 
  74 # Return the larger of two numbers...
  75 sub max ($$) {
  76   my($Value1, $Value2) = @_;
  77 
  78   return ($Value1 >= $Value2) ? $Value1 : $Value2;
  79 }
  80 
  81 # Return a pseudo random number between:
  82 # . 0 and 1
  83 # . 0 and specified number
  84 # . specified number 1 and number 2
  85 #
  86 sub random (;$$) {
  87   my($Value1, $Value2) = @_;
  88   my($RandomValue);
  89 
  90   if (defined($Value1) && defined($Value2)) {
  91     my($Value) = max($Value1, $Value2) - min($Value1, $Value2);
  92     $RandomValue = $Value1 + CORE::rand($Value);
  93   }
  94   elsif (defined($Value1)) {
  95     $RandomValue = CORE::rand($Value1);
  96   }
  97   else {
  98     $RandomValue = CORE::rand();
  99   }
 100   return $RandomValue;
 101 }
 102 
 103 # Round a integer/real number to:
 104 # . A nearest integer
 105 # . Specified number of decimal places
 106 #
 107 sub round ($;$) {
 108   my($Value, $DecimalPlaces) = @_;
 109   my($RoundedValue);
 110 
 111   if (defined($DecimalPlaces) && $DecimalPlaces > 0) {
 112     $RoundedValue = sprintf "%.${DecimalPlaces}f", $Value;
 113   }
 114   else {
 115     if ($Value < 0) {
 116       $RoundedValue = int($Value - 0.5);
 117     }
 118     else {
 119       $RoundedValue = int($Value + 0.5);
 120     }
 121   }
 122   return $RoundedValue;
 123 }
 124 
 125 # Return tangent of an angle expressed in radians.
 126 sub tan {
 127   my($Value) = @_;
 128 
 129   return (CORE::sin($Value)/CORE::cos($Value));
 130 }
 131 
 132 # Return inverse sine of an angle expressed in radians.
 133 #
 134 # For a right angle triangle defined by sides X and Y in a unit circle, Pythagorean theorem implies
 135 # X**2 + Y**2 = 1 and sin value corresponds to Y. So asin is equivalent to atan2(Y, sqrt(1-Y**2)).
 136 # However, taking sqrt of negative numbers is problematic; Math::Trig::asin handles it using complex
 137 # numbers.
 138 #
 139 sub asin ($) {
 140   my($Value) = @_;
 141 
 142   return Math::Trig::asin($Value);
 143 }
 144 
 145 # Return inverse cosine of an angle expressed in radians.
 146 #
 147 # For a right angle triangle defined by sides X and Y in a unit circle, Pythagorean theorem implies
 148 # X**2 + Y**2 = 1 and cos value corresponds to X. So asin is equivalent to atan2(sqrt(1-X**2), X)
 149 # However, taking sqrt of negative numbers is problematic; Math::Trig::acos handles it using complex
 150 # numbers.
 151 #
 152 sub acos ($) {
 153   my($Value) = @_;
 154 
 155   return Math::Trig::acos($Value);
 156 }
 157