home *** CD-ROM | disk | FTP | other *** search
- # Macros to convert signed decimal numbers to two's complement hexadecimal
- # notation. This version does not use machine arithmetic; it does everything
- # with strings, so is able to handle integers of any size. As written it
- # accommodates word sizes of 4, 8, 16, 32, 64, and 128 bits. Other word
- # sizes can be added by changing the definitions at the top.
- #
- # Because machine arithmetic is not used, this version is considerably slower
- # than the first one but it works for numbers that don't fit in 32 bits in
- # Kermit 95 and in 32-bit versions of C-Kermit.
- #
- # F. da Cruz, Columbia University, 28 December 2007
-
- .legal = :4:8:16:32:64:128: # Legal word sizes
-
- # Largest positive integer for the supported word sizes
-
- .maxint<4> = 7
- .maxint<8> = 127
- .maxint<16> = 32767
- .maxint<32> = 2147483647
- .maxint<64> = 9223372036854775807
- .maxint<128> = 340282366920938463463374607431768211455
-
- # Ditto plus one (because we can't necessarily do arithmetic on big numbers)
-
- .maxplusone<4> = 8
- .maxplusone<8> = 128
- .maxplusone<16> = 32768
- .maxplusone<32> = 2147483648
- .maxplusone<64> = 9223372036854775808
- .maxplusone<128> = 340282366920938463463374607431768211456
-
- # Macro BINTOHEX converts a binary string to hex.
- # \%1 = binary number (string)
- # \%2 = word size in bits
- #
- # \fradix() is constrained by machine integer word length
- # so we do it in pieces in case the number is too big.
- #
- define BINTOHEX {
- undef \%6 # Result accumulator
- .\%1 := \flpad(\%1,\%2,0) # Pad to size if necessary
- for \%9 1 \%2 4 { # Do four bits at at a time
- .\%8 := \fsubstr(\%1,\%9,4) # Get chunk of 4
- if not def \%8 break # Make sure we have one
- .\%7 := \fradix(\%8,2,16) # Convert to Hex digit
- .\%6 := \%6\%7 # Accumulate
- }
- return \%6
- }
-
- def DIV2 { # Divide decimal string by two
- local \%i
- undef \%6 \%7 result
- for \%i 1 \flen(\%1) 1 { # One digit at a time.
- .\%9 := \%7\:(\%1[\%i:1]) # Get a digit.
- .\%8 ::= \%9/2 # Divide it by 2
- .\%7 ::= \%9%2 # Get remainder
- .\%6 := \%6\%8 # Accumulate result
- }
- .result := \%6 # Make result
- .remainder := \%7 # and remainder visible
- }
-
- def DTOB { # Convert decimal string to binary
- while true { # without using machine
- div2 \%1 # arithmetic.
- .\%6 := \m(remainder)\%6
- .\%1 := \m(result)
- if not \fverify(0,\%1) break
- }
- return \%6
- }
- # Macro DECTOHEX converts a signed decimal number to 2's complement hex,
- # using the macros defined above as workers.
- # \%1 = decimal number string (default 0)
- # \%2 = word size in bits
- # (must be a power of two, 4 or greater, default 32, max 128)
- # Returns result in \v(result) and/or as value of \fexec(dectohex arg arg).
- #
- define DECTOHEX {
- local digits
- if not def \%1 .\%1 = 0 # Supply default if no arg given
- if not numeric \%1 return NOT_A_NUMBER:\%1 # Check that arg is a number
- if not def \%2 .\%2 := 32 # Use 32 bits if no second arg
- if not \findex(:\%2:,\m(legal)) end 1 "UNSUPPORTED WORD SIZE - \%2"
- .digits := \flen(\m(maxint<\%2>)) # Number of digits in it
-
- if eq "\fsubstr(\%1,1,1)" "+" .\%1 := \fsubstr(\%1,2) # strip any + sign
- if not eq "\fsubstr(\%1,1,1)" "-" { # If argument is not signed...
- if lgt \flpad(\%1,\m(digits),0) \m(maxint<\%2>) return OVERFLOW
- dtob \%1 # Convert from decimal to binary
- bintohex \v(return) \%2 # And from binary to hex
- return \flpad(\v(return),(\%2/4),0) # Return padded result
- }
- .\%1 := \fsubstr(\%1,2) # Negative number - remove sign
- .\%1 := \flpad(\%1,\flen(\m(maxint<\%2>)),0) # Must use lexical comparison
- if llt \m(maxplusone<\%2>) \%1 return UNDERFLOW # Check magnitude
- dtob \%1 # Convert to binary
- .\%9 := \flpad(\v(return),\%2,0) # and pad
- .\%8 ::= \frindex(1,\%9) - 1 # Find first 1 on the right
- if == \%8 -1 return \frepeat(0,\%2 / 4) # Watch out for negative 0
- .\%7 := \fsubstr(\%9,1,\%8) # Split string here
- .\%6 := \fsubstitute(\%7,01,10) # Complement bits in left part
- .\%5 := \%6\fsubstr(\%9,\%8+1) # Put back with right part
- .\%4 := \fexec(bintohex \%5 \%2) # Convert to hex
- return \%4
- }
- # Test the functions...
-
- def try {
- # Note \v(time) lacks the fractional part in Windows for some reason.
- .t1 := \v(ftime) # Current time
- .result := \fexec(dectohex \%1 \%2) # Do the conversion
- .t2 := \v(ftime) # New time
- (setq t3 (- t2 t1)) # Difference
- echo \%1[\%2] = \m(result) [\ffpround(\m(t3),2) sec] # Print
- }
- try 7 # No word size specified
-
- try 7 4 # 4-bit word
- try 8 4
- try -8 4
- try -9 4
- try 99 4
-
- try 0 8 # 8-bit word
- try -0 8
- try 1 8
- try +1 8
- try 2 8
- try 3 8
- try 4 8
- try 5 8
- try 6 8
- try 7 8
- try -1 8
- try -2 8
- try -3 8
- try -4 8
- try -5 8
- try -6 8
- try -7 8
- try -8 8
- try 64 8
- try 65 8
- try -128 8
-
- try 0 16 # 16-bit word
- try 64 16
- try 65 16
- try -128 16
- try -32768 16
- try 99999 16
- try -99999 16
-
- try 0 32 # 32-bit word
- try 1 32
- try 16383 32
- try 2147483647 32
- try -1 32
- try -2 32
- try -2147483647 32
- try -2147483648 32
-
- try 0 64 # 64-bit word
- try 2147483647 64
- try -1 64
- try -2 64
- try 1234567890 64
- try -2147483647 64
- try -2147483648 64
- try 8224373093854475231 64
-
- try 0 128 # 128-bit word
- try 1 128
- try -1 128
- try -2 128
- try 317282366902934863643347307341786875499 128
-
- if c-kermit exit
-