Mailing List Archive: 49091 messages

# bit shifts

### [1/9] from: hallvard::ystad::helpinhand::com at: 11-Sep-2001 19:22

Hi folks How do I use rebol for bit shifts? I feel like shifting the binary string 11101000 four places to the right, so it becomes "00001110". How do I do that?? ~H

### [2/9] from: ryanc:iesco-dms at: 11-Sep-2001 13:43

Something like this should suffice...
>> shift-right: func [series values] [ copy/part head insert copy series
values length? series]
>> byte: "11000011"
== "11000011"
>> shift-right byte "0000"
== "00001100"
>>
And to be symmetrical...
>> shift-left: func [series values] [ skip append copy series values length?
values]
>> shift-left byte "0000"
== "00110000"
>>
> Hi folks > How do I use rebol for bit shifts? I feel like shifting the binary string
<<quoted lines omitted: 6>>
> [rebol-request--rebol--com] with "unsubscribe" in the > subject, without the quotes.
-- Ryan Cole Programmer Analyst www.iesco-dms.com 707-468-5400

### [3/9] from: greggirwin:starband at: 11-Sep-2001 15:31

Hi Hallvard, << How do I use rebol for bit shifts? I feel like shifting the binary string 11101000 four places to the right, so it becomes "00001110". How do I do that?? >> If you're working with numeric values you can multiply or divide, by powers of two. For example (please correct any misinformation REBOLers!): shl: to-integer (value * (2 ** shift-count)) shr: to-integer (value / (2 ** shift-count)) That doesn't account for sign bits, negative numbers, and such but it's the general idea. If you have binary strings of 0 and 1 digits, maybe this will help: left: func [s len][return copy/part s len] right: func [s len][return copy at s ((length? s) - (len - 1))] mid: func [s start len][return copy/part at s start len] mk-string: func [n[integer!] ch[char! string!]][to-string array/initial n ch] bin-str: func [{Converts a string to a string of 1's and 0's, 1 per bit} s[string!]] [enbase/base s 2] unbin-str: func [{Converts a string from a string of 1's and 0's, 1 per bit, to a text string.} s[string!]] [to-string debase/base s 2] bin-str-shl: func [{Shifts a text string of 1's an 0's count "bits" left.} s[string!] count[integer!]] [ join mid s (count + 1) ((length? s) - count) mk-string count "0" ] bin-str-shr: func [{Shifts a text string of 1's an 0's count "bits" right.} s[string!] count[integer!]] [ join mk-string count "0" mid s 1 ((length? s) - count) ] bin-str-rol: func [{Rotates a text string of 1's an 0's count "bits" left.} s[string!] count[integer!]] [ join (mid s (count + 1) ((length? s) - count)) (left s count) ] bin-str-ror: func [{Rotates a text string of 1's an 0's count "bits" right.} s[string!] count[integer!]] [ join (right s count) mid s 1 ((length? s) - count) ] bin-str-val: func [s[string!]] [to-integer debase/base s 2] --Gregg

### [4/9] from: hallvard:ystad:helpinhand at: 20-Sep-2001 13:16

>> stats rebol
You are not a member of list 'rebol' ... strange, since I didn't unsubscribe... Anyway, I posted something earlier today, here goes again: Gregg Irwin skrev (Tuesday 11.09.2001, kl. 23.31):
>If you're working with numeric values you can multiply or divide, by >powers >of two. >For example (please correct any misinformation REBOLers!): > > shl: to-integer (value * (2 ** shift-count)) > shr: to-integer (value / (2 ** shift-count))
Well, this mostly works, but wheras the integer value 1 right-shifted becomes 0, the same value divided by 2 becomes 0,5. Even if one should round the value (how do we do so in rebol, by the way?), it would become 1, not 0. So I think it's better to shift "à proprement dire". Your other routines seem to work, but only partially, I'm afraid. It seems rebol has great problems with the debase function... But thanks anyway. ~H

### [5/9] from: greggirwin:starband at: 20-Sep-2001 6:45

Hi Hallvard, << Well, this mostly works, but wheras the integer value 1 right-shifted becomes 0, the same value divided by 2 becomes 0,5. Even if one should round the value (how do we do so in rebol, by the way?), it would become 1, not 0. So I think it's better to shift "à proprement dire".
>>
We're not dividing by 2 but by (2 ** n). Actual function definitions: shl: func [value shift-count] [to-integer (value * (2 ** shift-count))] shr: func [value shift-count] [to-integer (value / (2 ** shift-count))] I just did some quick tests and these seem to work just fine. Note that if you remove the to-integer calls, so they can go beyond 30 bit-shifts, then you can get decimal results. REBOL doesn't seem to have an integer-divide operator, so we'd have to do that ourselves. If you're only concerned about shifting too far to the right, you could do this: shr: func [value shift-count /local result] [ result: (value / (2 ** shift-count)) either result >= 1 [ return result ][ return 0 ] ] You can get bogus results by passing in a number that is not a power of 2 and shifting that (e.g. shr 25 2), so you have to decide what you want to do in that case. << Your other routines seem to work, but only partially, I'm afraid. It seems rebol has great problems with the debase function... But thanks anyway. >> Hmmm. I'll have to check it out. Thanks for letting me know. --Gregg

### [6/9] from: joel:neely:fedex at: 20-Sep-2001 3:04

> Gregg Irwin skrev (Tuesday 11.09.2001, kl. 23.31): > > If you're working with numeric values you can multiply or
<<quoted lines omitted: 8>>
> rebol, by the way?), it would become 1, not 0. So I think > it's better to shift "à proprement dire".
Right-shifting the value 1 by one digit produces the value 0.1 (one-half, if we're dealing with binary) which becomes 0 once TO-INTEGER deletes the fractional part. (TO-INTEGER truncates; it doesn't round, as shown by
>> to-integer 0.9999999
== 0 and similar exercises...) The same thing applies to right-shifting by a larger number of digits -- e.g. 27 right-shifted by 3 digits (in binary) 11011 -> 11.011 -> 11 and
>> to-integer 27 / (2 ** 3)
== 3 The nice thing about this formula is that the base is just another parameter, which could be changed to any other value one wishes. For example, using base 3, one can right-shift 25 by two "trits" (ternary digits) via
>> to-integer 25 / (3 ** 2)
== 2 with the details as before (in ternary, of course ;-) twentyfive -> 221 -> 2.21 -> 2 As for your other question,
> ... Even if one should round the value (how do we do so in > rebol, by the way?)...
one can round by adding the bias prior to applying TO-INTEGER as in round-to-int: func [x [decimal!]] [to-integer x + 0.5]
>> round-to-int 1.4 == 1 >> round-to-int 1.5 == 2 >> round-to-int 1.6 == 2
or to a specified number of (fractional) decimal digits by round-decimal: func [ x [decimal!] ndigs [integer!] /local factor ][ factor: 10 ** ndigs (to-integer x * factor + 0.5) / factor ]
>> round-decimal 1.23456 1 == 1.2 >> round-decimal 1.23456 2 == 1.23 >> round-decimal 1.23456 3 == 1.235 >> round-decimal 1.23456 4 == 1.2346
A negative number of digits actually rounds away the non- fractional digits, as well:
>> round-decimal 1234.5678 1 == 1234.6 >> round-decimal 1234.5678 0 == 1235 >> round-decimal 1234.5678 -1 == 1230 >> round-decimal 1234.5678 -2 == 1200
HTH! -jn- -- ------------------------------------------------------------ Programming languages: compact, powerful, simple ... Pick any two! joel'dot'neely'at'fedex'dot'com

### [7/9] from: greggirwin:starband at: 20-Sep-2001 10:23

Hi Hallvard, << It seems rebol has great problems with the debase function... >> I forgot to ask, can you give me an example or two of how it fails? Thanks! --Gregg

### [8/9] from: hallvard:ystad:helpinhand at: 20-Sep-2001 19:12

Gregg Irwin skrev (Thursday 20.09.2001, kl. 18.23):
>I forgot to ask, can you give me an example or two of how it fails?
Sure. I'm posting it to the list, since the results are odd. And maybe someone feels like trying to reproduce this on some other platforms than mine? Here we go (from my windows2000):
>> print to-integer debase/base "F2" 16
62
>> print to-integer debase/base "10" 2
0 On my SuSE linux 7.1, I got this:
>> print debase/base "10101010" 2
** Script Error: Not enough memory ** Where: halt-view ** Near: print debase/base "10101010" 2
>> print debase/base "10101" 2
none
>>
(Not enough memory? 256M RAM?) And then this:
>> print to-integer debase/base "F2" 16
Segmentation fault allvardo:/rebol # The rebol console vanishes, but the process is still running: allvardo:/rebol # ps aux | grep rebol root 24283 0.0 0.3 3040 820 pts/1 S 19:03 0:00 ./rebol Your bin-str-val function: bin-str-val: func [s[string!]] [to-integer debase/base s 2] sometimes crashes on my windows machine. The whole rebol console disappears. I haven't been able to reproduce this on my linux. There you go. Hope this helps someone in some way. ~H