home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / scripts / ckermit / twoscomplementv2.~1~ < prev    next >
Text File  |  2007-12-27  |  6KB  |  181 lines

  1. # Macros to convert signed decimal numbers to two's complement hexadecimal
  2. # notation.  This version does not use machine arithmetic; it does everything
  3. # with strings, so is able to handle integers of any size.  As written it
  4. # accommodates word sizes of 4, 8, 16, 32, 64, and 128 bits.  Other word
  5. # sizes can be added by changing the definitions at the top.
  6. # Because machine arithmetic is not used, this version is considerably slower
  7. # than the first one but it works for numbers that don't fit in 32 bits in
  8. # Kermit 95 and in 32-bit versions of C-Kermit.
  9. #
  10. # F. da Cruz, Columbia University, 28 December 2007
  11.  
  12. .legal = :4:8:16:32:64:128:             # Legal word sizes
  13.  
  14. # Largest positive integer for the supported word sizes
  15.  
  16. .maxint<4> = 7
  17. .maxint<8> = 127
  18. .maxint<16> = 32767
  19. .maxint<32> = 2147483647
  20. .maxint<64> = 9223372036854775807
  21. .maxint<128> = 340282366920938463463374607431768211455
  22.  
  23. # Ditto plus one (because we can't necessarily do arithmetic on big numbers)
  24.  
  25. .maxplusone<4> = 8
  26. .maxplusone<8> = 128
  27. .maxplusone<16> = 32768
  28. .maxplusone<32> = 2147483648
  29. .maxplusone<64> = 9223372036854775808
  30. .maxplusone<128> = 340282366920938463463374607431768211456
  31.  
  32. # Macro BINTOHEX converts a binary string to hex.
  33. #   \%1 = binary number (string)
  34. #   \%2 = word size in bits
  35. # \fradix() is constrained by machine integer word length
  36. # so we do it in pieces in case the number is too big.
  37. #
  38. define BINTOHEX {
  39.     undef \%6                                # Result accumulator
  40.     .\%1 := \flpad(\%1,\%2,0)                # Pad to size if necessary
  41.     for \%9 1 \%2 4 {                        # Do four bits at at a time
  42.         .\%8 := \fsubstr(\%1,\%9,4)          # Get chunk of 4
  43.         if not def \%8 break                 # Make sure we have one
  44.         .\%7 := \fradix(\%8,2,16)            # Convert to Hex digit
  45.         .\%6 := \%6\%7                       # Accumulate
  46.     }
  47.     return \%6
  48. }
  49.  
  50. def DIV2 {                                   # Divide decimal string by two
  51.     undef \%6 \%7 result
  52.     for \%i 1 \flen(\%1) 1 {                 # One digit at a time.
  53.         .\%9 := \%7\:(\%1[\%i:1])            # Get a digit.
  54.         .\%8 ::= \%9/2                       # Divide it by 2
  55.         .\%7 ::= \%9%2                       # Get remainder
  56.         .\%6 := \%6\%8                       # Accumulate result
  57.     }
  58.     .result := \%6                           # Make result 
  59.     .remainder := \%7                        # and remainder visible
  60. }
  61.  
  62. def DTOB {                                   # Convert decimal string to binary
  63.     while true {                             # without using machine 
  64.         div2 \%1                             # arithmetic.
  65.         .\%6 := \m(remainder)\%6
  66.         .\%1 := \m(result)                    
  67.         if not \fverify(0,\%1) break
  68.     }        
  69.     return \%6
  70. }
  71. # Macro DECTOHEX converts a signed decimal number to 2's complement hex,
  72. # using the macros defined above as workers.
  73. #   \%1 = decimal number string (default 0)
  74. #   \%2 = word size in bits
  75. #         (must be a power of two, 4 or greater, default 32, max 128)
  76. #   Returns result in \v(result) and/or as value of \fexec(dectohex arg arg).
  77. #
  78. define DECTOHEX {
  79.     local digits
  80.     if not def \%1 .\%1 = 0                  # Supply default if no arg given
  81.     if not numeric \%1 return NOT_A_NUMBER:\%1  # Check that arg is a number
  82.     if not def \%2 .\%2 := 32                   # Use 32 bits if no second arg
  83.     if not \findex(:\%2:,\m(legal)) end 1 "UNSUPPORTED WORD SIZE - \%2"
  84.     .digits := \flen(\m(maxint<\%2>))           # Number of digits in it
  85.  
  86.     if eq "\fsubstr(\%1,1,1)" "+" .\%1 := \fsubstr(\%1,2) # strip any + sign
  87.     if not eq "\fsubstr(\%1,1,1)" "-" {      # If argument is not signed...
  88.         if lgt \flpad(\%1,\m(digits),0) \m(maxint<\%2>) return OVERFLOW
  89.         dtob \%1                             # Convert from decimal to binary
  90.         bintohex \v(return) \%2              # And from binary to hex
  91.         return \flpad(\v(return),(\%2/4),0)  # Return padded result
  92.     }
  93.     .\%1 := \fsubstr(\%1,2)                  # Negative number - remove sign
  94.     .\%1 := \flpad(\%1,\flen(\m(maxint<\%2>)),0) # Must use lexical comparison
  95.     if llt \m(maxplusone<\%2>) \%1 return UNDERFLOW # Check magnitude
  96.     dtob \%1                                 # Convert to binary
  97.     .\%9 := \flpad(\v(return),\%2,0)         # and pad
  98.     .\%8 ::= \frindex(1,\%9) - 1             # Find first 1 on the right
  99.     if == \%8 -1 return \frepeat(0,\%2 / 4)  # Watch out for negative 0
  100.     .\%7 := \fsubstr(\%9,1,\%8)              # Split string here
  101.     .\%6 := \fsubstitute(\%7,01,10)          # Complement bits in left part
  102.     .\%5 := \%6\fsubstr(\%9,\%8+1)           # Put back with right part
  103.     .\%4 := \fexec(bintohex \%5 \%2)         # Convert to hex
  104.     return \%4
  105. }
  106. # Test the functions...
  107.  
  108. def try {
  109.     # Note \v(time) lacks the fractional part in Windows for some reason.
  110.     .t1 := \v(ftime)                    # Current time
  111.     .result := \fexec(dectohex \%1 \%2) # Do the conversion
  112.     .t2 := \v(ftime)                    # New time
  113.     (setq t3 (- t2 t1))                 # Difference
  114.     echo \%1[\%2] = \m(result) [\ffpround(\m(t3),2) sec] # Print
  115. }
  116. try 7          # No word size specified
  117.  
  118. try  7 4       # 4-bit word
  119. try  8 4
  120. try -8 4
  121. try -9 4
  122. try 99 4
  123.  
  124. try  0 8        # 8-bit word
  125. try -0 8
  126. try  1 8
  127. try +1 8
  128. try  2 8
  129. try  3 8
  130. try  4 8
  131. try  5 8
  132. try  6 8
  133. try  7 8
  134. try -1 8
  135. try -2 8
  136. try -3 8
  137. try -4 8
  138. try -5 8
  139. try -6 8
  140. try -7 8
  141. try -8 8
  142. try 64 8
  143. try 65 8
  144. try -128 8
  145.  
  146. try 0 16       # 16-bit word
  147. try 64 16
  148. try 65 16
  149. try -128 16
  150. try -32768 16
  151. try 99999 16
  152. try -99999 16
  153.  
  154. try 0 32       # 32-bit word
  155. try 1 32
  156. try 16383 32
  157. try 2147483647 32
  158. try -1 32
  159. try -2 32
  160. try -2147483647 32
  161. try -2147483648 32
  162.  
  163. try 0 64       # 64-bit word
  164. try 2147483647 64
  165. try -1 64
  166. try -2 64
  167. try  1234567890 64
  168. try -2147483647 64
  169. try -2147483648 64
  170. try  8224373093854475231 64
  171.  
  172. try 0 128      # 128-bit word
  173. try 1 128
  174. try -1 128
  175. try -2 128
  176. try 317282366902934863643347307341786875499 128
  177.  
  178. if c-kermit exit
  179.