       1 package ConversionsUtil;
       2 #
       3 # File: ConversionsUtil.pm
       4 # Author: Manish Sud <msud@san.rr.com>
       5 #
       6 # Copyright (C) 2018 Manish Sud. All rights reserved.
       7 #
       8 # This file is part of MayaChemTools.
       9 #
      10 # MayaChemTools is free software; you can redistribute it and/or modify it under
      11 # the terms of the GNU Lesser General Public License as published by the Free
      12 # Software Foundation; either version 3 of the License, or (at your option) any
      13 # later version.
      14 #
      15 # MayaChemTools is distributed in the hope that it will be useful, but without
      16 # any warranty; without even the implied warranty of merchantability of fitness
      17 # for a particular purpose.  See the GNU Lesser General Public License for more
      18 # details.
      19 #
      20 # You should have received a copy of the GNU Lesser General Public License
      21 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
      22 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
      23 # Boston, MA, 02111-1307, USA.
      24 #
      25
      26 use strict;
      27 use Exporter;
      28 use Constants;
      29
      30 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
      31
      32 @ISA = qw(Exporter);
      33
      34 # Groups of conversion functions...
      35 my(@MathConversions) = qw(DegreesToRadians RadiansToDegrees);
      36 my(@NumericBaseConversions) = qw(BinaryToDecimal DecimalToBinary HexadecimalToDecimal DecimalToHexadecimal OctalToDecimal DecimalToOctal BinaryToHexadecimal HexadecimalToBinary HexadecimalToOctal OctalToHexadecimal StringToBinary StringToHexadecimal);
      37
      38 # Export all conversion functions...
      39 @EXPORT = (@MathConversions, @NumericBaseConversions);
      40 @EXPORT_OK = qw();
      41
      42 %EXPORT_TAGS = (
      43                 math => [@MathConversions],
      44                 all  => [@EXPORT, @EXPORT_OK]
      45                );
      46
      47
      48 # Degrees to radians...
      49 sub DegreesToRadians ($;$) {
      50   my($Degrees, $IgnoreWrap) = @_;
      51   my($Radians, $WrapValue);
      52
      53   $WrapValue = (defined($IgnoreWrap) && $IgnoreWrap) ? 0 : 1;
      54   if ($Degrees > 360 && $WrapValue) {
      55     $Degrees = $Degrees % 360;
      56   }
      57   $Radians = ($Degrees * TwoPi) / 360;
      58
      59   return $Radians;
      60 }
      61
      62 # Radians to degrees...
      63 sub RadiansToDegrees ($;$) {
      64   my($Radians, $IgnoreWrap) = @_;
      65   my($Degrees, $WrapValue);
      66
      67   $WrapValue = (defined($IgnoreWrap) && $IgnoreWrap) ? 0 : 1;
      68   $Degrees = ($Radians * 360) / TwoPi;
      69   if ($Degrees > 360 && $WrapValue) {
      70     $Degrees = $Degrees % 360;
      71   }
      72
      73   return $Degrees;
      74 }
      75
      76 # Convert a binary string to a decimal number...
      77 sub BinaryToDecimal ($) {
      78   my($Value) = @_;
      79
      80   if ($Value !~ /^0b/) {
      81     $Value = "0b${Value}";
      82   }
      83   return _ConvertToDecimal($Value);
      84 }
      85
      86 # Convert a decimal number into a binary string...
      87 sub DecimalToBinary ($) {
      88   my($Value) = @_;
      89
      90   return sprintf("%b", $Value);
      91 }
      92
      93 # Convert a hexadecimal string to a decimal number...
      94 sub HexadecimalToDecimal ($) {
      95   my($Value) = @_;
      96
      97   if ($Value !~ /^0x/) {
      98     $Value = "0x${Value}";
      99   }
     100   return _ConvertToDecimal($Value);
     101 }
     102
     103 # Convert a decimal number into a hexadecimal string...
     104 sub DecimalToHexadecimal ($) {
     105   my($Value) = @_;
     106
     107   return sprintf("%x", $Value);
     108 }
     109
     110 # Convert an octal string to a decimal number...
     111 sub OctalToDecimal ($) {
     112   my($Value) = @_;
     113
     114   if ($Value !~ /^0/) {
     115     $Value = "0${Value}";
     116   }
     117   return _ConvertToDecimal($Value);
     118 }
     119
     120 # Convert a decimal number into an octal string...
     121 sub DecimalToOctal ($) {
     122   my($Value) = @_;
     123
     124   return sprintf("%o", $Value);
     125 }
     126
     127 # Convert string into a binary string. Going from left to right, two ways of arranging bits
     128 # inside each byte are available: Most Significat Bits (MSB) first or Least Significat Bits (LSB)
     129 # first. Default is MSB corresponding to  descending bits order (PerlSpeak) inside each
     130 # each packed byte (Most singificat bits first).
     131 #
     132 sub StringToBinary ($;$) {
     133   my($Value, $UseReverseBitOrder) = @_;
     134   my($BinTemplate);
     135
     136   $BinTemplate = (defined($UseReverseBitOrder) && $UseReverseBitOrder) ? 'b*' : 'B*';
     137   return unpack($BinTemplate, $Value);
     138 }
     139
     140 # Convert string into a hexadecimal string. Two ways of arranging nybbles (pair of 4 bits in each
     141 # byte) are available: high nybbles first or low nybbles first. Default is MSB corresponding to high
     142 # nybbles (PerlSpeak) first. Low and high nybbles correspond to pair of a low and high four bits in a byte.
     143 #
     144 sub StringToHexadecimal ($;$) {
     145   my($Value, $UseReverseBitOrder) = @_;
     146   my($HexTemplate);
     147
     148   $HexTemplate = (defined($UseReverseBitOrder) && $UseReverseBitOrder) ? 'h*' : 'H*';
     149   return unpack($HexTemplate, $Value);
     150 }
     151
     152 # Convert a binary string into a hexadecimal string...
     153 #
     154 sub BinaryToHexadecimal ($;$) {
     155   my($Value, $UseReverseBitOrder) = @_;
     156   my($BinTemplate, $HexTemplate);
     157
     158   $BinTemplate = (defined($UseReverseBitOrder) && $UseReverseBitOrder) ? 'b*' : 'B*';
     159   $HexTemplate = (defined($UseReverseBitOrder) && $UseReverseBitOrder) ? 'h*' : 'H*';
     160
     161   return unpack($HexTemplate, pack($BinTemplate, $Value));
     162 }
     163
     164 # Convert a hexadecimal string into a binary string...
     165 #
     166 sub HexadecimalToBinary ($;$) {
     167   my($Value, $UseReverseBitOrder) = @_;
     168   my($BinTemplate, $HexTemplate);
     169
     170   $BinTemplate = (defined($UseReverseBitOrder) && $UseReverseBitOrder) ? 'b*' : 'B*';
     171   $HexTemplate = (defined($UseReverseBitOrder) && $UseReverseBitOrder) ? 'h*' : 'H*';
     172
     173   return unpack($BinTemplate, pack($HexTemplate, $Value));
     174 }
     175
     176 # Convert a hexadecimal string into a octal string...
     177 #
     178 sub HexadecimalToOctal {
     179   my($Hexadecimal) = @_;
     180
     181   return DecimalToOctal(HexadecimalToDecimal($Hexadecimal));
     182 }
     183
     184 # Convert a octal string into a hexadecimal string...
     185 #
     186 sub OctalToHexadecimal {
     187   my($Octal) = @_;
     188
     189   return DecimalToHexadecimal(OctalToDecimal($Octal));
     190 }
     191
     192 # Use Perl oct function to convert binary, octal or hexadecimal strings into decimal numbers.
     193 sub _ConvertToDecimal ($) {
     194   my($Value) = @_;
     195
     196   return ($Value =~ /^0/) ? oct($Value) : $Value;
     197 }
     198