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