home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ckscripts / twoscomplementv2 < prev    next >
Text File  |  2020-01-01  |  6KB  |  182 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.     local \%i
  52.     undef \%6 \%7 result
  53.     for \%i 1 \flen(\%1) 1 {                 # One digit at a time.
  54.         .\%9 := \%7\:(\%1[\%i:1])            # Get a digit.
  55.         .\%8 ::= \%9/2                       # Divide it by 2
  56.         .\%7 ::= \%9%2                       # Get remainder
  57.         .\%6 := \%6\%8                       # Accumulate result
  58.     }
  59.     .result := \%6                           # Make result 
  60.     .remainder := \%7                        # and remainder visible
  61. }
  62.  
  63. def DTOB {                                   # Convert decimal string to binary
  64.     while true {                             # without using machine 
  65.         div2 \%1                             # arithmetic.
  66.         .\%6 := \m(remainder)\%6
  67.         .\%1 := \m(result)                    
  68.         if not \fverify(0,\%1) break
  69.     }        
  70.     return \%6
  71. }
  72. # Macro DECTOHEX converts a signed decimal number to 2's complement hex,
  73. # using the macros defined above as workers.
  74. #   \%1 = decimal number string (default 0)
  75. #   \%2 = word size in bits
  76. #         (must be a power of two, 4 or greater, default 32, max 128)
  77. #   Returns result in \v(result) and/or as value of \fexec(dectohex arg arg).
  78. #
  79. define DECTOHEX {
  80.     local digits
  81.     if not def \%1 .\%1 = 0                  # Supply default if no arg given
  82.     if not numeric \%1 return NOT_A_NUMBER:\%1  # Check that arg is a number
  83.     if not def \%2 .\%2 := 32                   # Use 32 bits if no second arg
  84.     if not \findex(:\%2:,\m(legal)) end 1 "UNSUPPORTED WORD SIZE - \%2"
  85.     .digits := \flen(\m(maxint<\%2>))           # Number of digits in it
  86.  
  87.     if eq "\fsubstr(\%1,1,1)" "+" .\%1 := \fsubstr(\%1,2) # strip any + sign
  88.     if not eq "\fsubstr(\%1,1,1)" "-" {      # If argument is not signed...
  89.         if lgt \flpad(\%1,\m(digits),0) \m(maxint<\%2>) return OVERFLOW
  90.         dtob \%1                             # Convert from decimal to binary
  91.         bintohex \v(return) \%2              # And from binary to hex
  92.         return \flpad(\v(return),(\%2/4),0)  # Return padded result
  93.     }
  94.     .\%1 := \fsubstr(\%1,2)                  # Negative number - remove sign
  95.     .\%1 := \flpad(\%1,\flen(\m(maxint<\%2>)),0) # Must use lexical comparison
  96.     if llt \m(maxplusone<\%2>) \%1 return UNDERFLOW # Check magnitude
  97.     dtob \%1                                 # Convert to binary
  98.     .\%9 := \flpad(\v(return),\%2,0)         # and pad
  99.     .\%8 ::= \frindex(1,\%9) - 1             # Find first 1 on the right
  100.     if == \%8 -1 return \frepeat(0,\%2 / 4)  # Watch out for negative 0
  101.     .\%7 := \fsubstr(\%9,1,\%8)              # Split string here
  102.     .\%6 := \fsubstitute(\%7,01,10)          # Complement bits in left part
  103.     .\%5 := \%6\fsubstr(\%9,\%8+1)           # Put back with right part
  104.     .\%4 := \fexec(bintohex \%5 \%2)         # Convert to hex
  105.     return \%4
  106. }
  107. # Test the functions...
  108.  
  109. def try {
  110.     # Note \v(time) lacks the fractional part in Windows for some reason.
  111.     .t1 := \v(ftime)                    # Current time
  112.     .result := \fexec(dectohex \%1 \%2) # Do the conversion
  113.     .t2 := \v(ftime)                    # New time
  114.     (setq t3 (- t2 t1))                 # Difference
  115.     echo \%1[\%2] = \m(result) [\ffpround(\m(t3),2) sec] # Print
  116. }
  117. try 7          # No word size specified
  118.  
  119. try  7 4       # 4-bit word
  120. try  8 4
  121. try -8 4
  122. try -9 4
  123. try 99 4
  124.  
  125. try  0 8        # 8-bit word
  126. try -0 8
  127. try  1 8
  128. try +1 8
  129. try  2 8
  130. try  3 8
  131. try  4 8
  132. try  5 8
  133. try  6 8
  134. try  7 8
  135. try -1 8
  136. try -2 8
  137. try -3 8
  138. try -4 8
  139. try -5 8
  140. try -6 8
  141. try -7 8
  142. try -8 8
  143. try 64 8
  144. try 65 8
  145. try -128 8
  146.  
  147. try 0 16       # 16-bit word
  148. try 64 16
  149. try 65 16
  150. try -128 16
  151. try -32768 16
  152. try 99999 16
  153. try -99999 16
  154.  
  155. try 0 32       # 32-bit word
  156. try 1 32
  157. try 16383 32
  158. try 2147483647 32
  159. try -1 32
  160. try -2 32
  161. try -2147483647 32
  162. try -2147483648 32
  163.  
  164. try 0 64       # 64-bit word
  165. try 2147483647 64
  166. try -1 64
  167. try -2 64
  168. try  1234567890 64
  169. try -2147483647 64
  170. try -2147483648 64
  171. try  8224373093854475231 64
  172.  
  173. try 0 128      # 128-bit word
  174. try 1 128
  175. try -1 128
  176. try -2 128
  177. try 317282366902934863643347307341786875499 128
  178.  
  179. if c-kermit exit
  180.