Mercurial > repos > deepakjadmin > mayatool3_test3
diff mayachemtools/lib/MathUtil.pm @ 0:73ae111cf86f draft
Uploaded
author | deepakjadmin |
---|---|
date | Wed, 20 Jan 2016 11:55:01 -0500 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mayachemtools/lib/MathUtil.pm Wed Jan 20 11:55:01 2016 -0500 @@ -0,0 +1,427 @@ +package MathUtil; +# +# $RCSfile: MathUtil.pm,v $ +# $Date: 2015/02/28 20:47:17 $ +# $Revision: 1.28 $ +# +# Author: Manish Sud <msud@san.rr.com> +# +# Copyright (C) 2015 Manish Sud. All rights reserved. +# +# This file is part of MayaChemTools. +# +# MayaChemTools is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3 of the License, or (at your option) any +# later version. +# +# MayaChemTools is distributed in the hope that it will be useful, but without +# any warranty; without even the implied warranty of merchantability of fitness +# for a particular purpose. See the GNU Lesser General Public License for more +# details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or +# write to the Free Software Foundation Inc., 59 Temple Place, Suite 330, +# Boston, MA, 02111-1307, USA. +# + +use strict; +use Exporter; +use Constants; +use Math::Trig (); +use POSIX (); + +use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS); + +@ISA = qw(Exporter); +@EXPORT = qw(acos asin atan tan ceil floor log10 min max srandom random round GeneratePrimeNumbersUpToLimit GeneratePrimeNumbersUpToCount); +@EXPORT_OK = qw(); + +%EXPORT_TAGS = (all => [@EXPORT, @EXPORT_OK] + ); + + +# Return next largest integer... +sub ceil ($) { + my($Value) = @_; + + return POSIX::ceil($Value); +} + +# Return previous smallest integer... +sub floor ($) { + my($Value) = @_; + + return POSIX::floor($Value); +} + +# Calculate log value using base 10... +sub log10 ($) { + my($Value) = @_; + + return CORE::log($Value)/CORE::log(10); +} + +# Return the smaller of two numbers... +sub min ($$) { + my($Value1, $Value2) = @_; + + return ($Value1 <= $Value2) ? $Value1 : $Value2; +} + +# Return the larger of two numbers... +sub max ($$) { + my($Value1, $Value2) = @_; + + return ($Value1 >= $Value2) ? $Value1 : $Value2; +} + +# The random number generator implemented in MayaChemTools is a variant of linear +# congruential generator (LCG) as described by Miller et al. [ Ref 120 ]. It is +# also referred to as Lehmer random number generator or Park-Miller random number +# generator. +# +# Unlike Perl's core random number generator function rand, the random number +# generator implemented in MayaChemTools generates consistent random values +# across different platforms - Windows, CygWin, Linux, Unix - for a specific random +# seed. +# + +# $RandomModulus = 2**31 - 1; +# $RandomMultiplier = 16807; +# $RandomQuotient = $RandomModulus / $RandomMultiplier; +# $RandomRemainder = $RandomModulus % $RandomMultiplier +# +# $MaxRandomSeed = 2*31 -2 +# +my($MaxRandomSeed, $RandomSeed, $RandomModulus, $RandomMultiplier, $RandomQuotient, $RandomRemainder); + +$MaxRandomSeed = 2147483646; +$RandomSeed = 123456789; + +$RandomModulus = 2147483647; +$RandomMultiplier = 16807; +$RandomQuotient = 127773; +$RandomRemainder = 2836; + +# Set random number seed... +# +# The intial value of random number seed is recommeded to be an integer between 1 +# and 2**31 - 2 [Ref 120] which translates to be 1 and 2147483646 +# +sub srandom ($) { + my($Seed) = @_; + + if ($Seed <= 0 ) { + die "Error: srandom: Specified seed value must be greater than 0..."; + } + + $RandomSeed = ($Seed > $MaxRandomSeed) ? ($Seed % $MaxRandomSeed) : $Seed; + + return $RandomSeed; +} + +# Retrun a random number between 0 and less than 1 or specified size... +# +sub random (;$) { + my($Size) = @_; + my($Value, $LowValue, $HighValue); + + $Size = defined $Size ? $Size : 1.0; + + $HighValue = $RandomSeed / $RandomQuotient; + $LowValue = $RandomSeed % $RandomQuotient; + + $Value = $RandomMultiplier * $LowValue - $RandomRemainder * $HighValue; + + $RandomSeed = ($Value > 0) ? $Value : ($Value + $RandomModulus); + + return ($RandomSeed / $RandomModulus) * $Size; +} + +# Round a integer/real number to: +# . A nearest integer +# . Specified number of decimal places +# +sub round ($;$) { + my($Value, $DecimalPlaces) = @_; + my($RoundedValue); + + if (defined($DecimalPlaces) && $DecimalPlaces > 0) { + $RoundedValue = sprintf "%.${DecimalPlaces}f", $Value; + } + else { + if ($Value < 0) { + $RoundedValue = int($Value - 0.5); + } + else { + $RoundedValue = int($Value + 0.5); + } + } + return $RoundedValue; +} + +# Return tangent of an angle expressed in radians. +sub tan { + my($Value) = @_; + + return (CORE::sin($Value)/CORE::cos($Value)); +} + +# Return inverse sine of an angle expressed in radians. +# +# For a right angle triangle defined by sides X and Y in a unit circle, Pythagorean theorem implies +# X**2 + Y**2 = 1 and sin value corresponds to Y. So asin is equivalent to atan2(Y, sqrt(1-Y**2)). +# However, taking sqrt of negative numbers is problematic; Math::Trig::asin handles it using complex +# numbers. +# +sub asin ($) { + my($Value) = @_; + + return Math::Trig::asin($Value); +} + +# Return inverse cosine of an angle expressed in radians. +# +# For a right angle triangle defined by sides X and Y in a unit circle, Pythagorean theorem implies +# X**2 + Y**2 = 1 and cos value corresponds to X. So asin is equivalent to atan2(sqrt(1-X**2), X) +# However, taking sqrt of negative numbers is problematic; Math::Trig::acos handles it using complex +# numbers. +# +sub acos ($) { + my($Value) = @_; + + return Math::Trig::acos($Value); +} + +# Generate prime numbers up to a specified limit and return a reference to an +# array containing the prime numbers. +# +# By default, the first 1000 prime numbers are generated. The 1000th prime +# number is 7919 and that's why default limit is set to 7920. +# +sub GeneratePrimeNumbersUpToLimit (;$) { + my($Limit) = @_; + + $Limit = defined $Limit ? $Limit : 7920; + + return _GeneratePrimeNumbers('ByLimit', $Limit) +} + +# Generate prime numbers up to specified count of prime numbers and return a +# reference to an array containing the prime numbers. +# +# By default, the first 1000 prime numbers are generated. The 1000th prime +# number is 7919. +# +sub GeneratePrimeNumbersUpToCount (;$) { + my($Count) = @_; + + $Count = defined $Count ? $Count : 1000; + + return _GeneratePrimeNumbers('ByCount', $Count) +} + +# Generate prime numbers up to specified limit or count and return a reference +# to an array containing the prime numbers. +# +# The algorithm to generate prime numbers is a modification of Sieve of Erastothenes +# prime number generator. +# +sub _GeneratePrimeNumbers { + my($Mode, $Value) = @_; + my($ByLimit, $PrimeNumber, $Number, $SqrtOfNumber, $NumberIsPrime, @PrimeNumbers); + + $ByLimit = ($Mode =~ /^ByLimit$/i) ? 1 : 0; + + @PrimeNumbers = (2, 3); + $Number = 3; + + # while ($Number <= $Limit) { + while ($ByLimit ? ($Number < $Value) : (@PrimeNumbers < $Value)) { + $Number += 2; + $SqrtOfNumber = sqrt $Number; + + $NumberIsPrime = 1; + PRIMENUMBER: for $PrimeNumber (@PrimeNumbers) { + if ($PrimeNumber > $SqrtOfNumber) { + last PRIMENUMBER; + } + if (!($Number % $PrimeNumber)) { + $NumberIsPrime = 0; + last PRIMENUMBER; + } + } + if ($NumberIsPrime) { + push @PrimeNumbers, $Number; + } + } + return \@PrimeNumbers; +} + +1; + +__END__ + +=head1 NAME + +MathUtil + +=head1 SYNOPSIS + +use MathUtil; + +use MathUtil qw(:all); + +=head1 DESCRIPTION + +B<MathUtil> module provides a variety of common math functions not available in core +Perl package or some other useful math utilities. In order to be consistent with other +Perl functions, name of all the functions in this package are in lowercase which differs +from MayaChemTools naming convention for function names. + +B<MathUtil> module provides the following functions: + +GeneratePrimeNumbersUpToCount, GeneratePrimeNumbersUpToLimit, acos, asin, ceil, +floor, log10, max, min, random, round, srandom, tan + +=head2 FUNCTIONS + +=over 4 + +=item B<GeneratePrimeNumbersUpToCount> + + $PrimesRef = GeneratePrimeNumbersUpToCount(); + $PrimesRef = GeneratePrimeNumbersUpToCount($Count); + +Generate prime numbers up to specified I<Count> of prime numbers and return a +reference to an array containing the prime numbers. + +By default, the first 1000 prime numbers are generated. The 1000th prime +number is 7919. + +The algorithm to generate prime numbers is a modification of Sieve of Erastothenes +prime number generator. + +=item B<GeneratePrimeNumbersUpToLimit> + + $PrimesRef = GeneratePrimeNumbersUpToLimit(); + $PrimesRef = GeneratePrimeNumbersUpToLimit($Limit); + +Generate prime numbers up to a specified I<Limit> and return a reference to an +array containing the prime numbers. + +By default, the first 1000 prime numbers are generated. The 1000th prime +number is 7919 and that's why default limit is set to 7920. + +The algorithm to generate prime numbers is a modification of Sieve of Erastothenes +prime number generator. + +=item B<acos> + + $Value = acos($AngleInRadians); + +Returns the nverse cosine of an angle expressed in I<Radians> using Math::Trig::acos +function. + +=item B<asin> + + $Value = asin($AngleInRadians); + +Returns the inverse sine of an angle expressed in I<Radians> using Math::Trig::asin +function. + +=item B<ceil> + + $IntegerValue = ceil($Value); + +Returns the next largest integer for I<Value> using POSIX::ceil function. + +=item B<floor> + + $IntegerValue = floor($Value); + +Returns the previous smallest integer for I<Value> using POSIX::floor function. + +=item B<log10> + + $Log10Value = log10($Value); + +Returns the log of I<Value> using base 10. + +=item B<max> + + $Number = max($Number1, $Number2); + +Returns a B<Number> corresponding to the maximum of I<Number1> and I<Number2>. + +=item B<min> + + $Number = min($Number1, $Number2); + +Returns a B<Number> corresponding to the minimum of I<Number1> and I<Number2>. + +=item B<round> + + $RoundedValue = round($Number); + $RoundedValue = round($Number, $DecimalPlaces); + +Returns a value corresponding to a nearst ingeter for I<Number> or formatted to I<DecimalPlaces>. + +=item B<random> + + $RandomNumber = random(); + $RandomNumber = random($Size); + +Returns a random number between 0 and less than 1 or specified size. + +The random number generator implemented in MayaChemTools is a variant of linear +congruential generator (LCG) as described by Miller et al. [ Ref 120 ]. It is +also referred to as Lehmer random number generator or Park-Miller random number +generator. + +Unlike Perl's core random number generator function rand, the random number +generator implemented in MayaChemTools generates consistent random values +across different platforms - Windows, CygWin, Linux, Unix - for a specific random +seed. + +=item B<srandom> + + $Seed = srandom($Seed); + +Sets random number seed to be used by <random> function and returns seed value. + +The random number seed is recommeded to be an integer between 1 and 2**31 - 2 +[Ref 120] which translates to be 1 and 2147483646. + +The default seed is set to 123456789. + +=item B<tan> + + $Value = tan($AngleInRadians); + +Returns the tangent of an angle expressed in I<Radians>. + +=back + +=head1 AUTHOR + +Manish Sud <msud@san.rr.com> + +=head1 SEE ALSO + +Constants.pm, ConversionsUtil.pm + +=head1 COPYRIGHT + +Copyright (C) 2015 Manish Sud. All rights reserved. + +This file is part of MayaChemTools. + +MayaChemTools is free software; you can redistribute it and/or modify it under +the terms of the GNU Lesser General Public License as published by the Free +Software Foundation; either version 3 of the License, or (at your option) +any later version. + +=cut