# 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"

>>

--Ryan
Hallvard Ystad wrote:

> 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

Hi, Hallvard,
Hallvard Ystad wrote:

> 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

### [9/9] from: ryanc:iesco-dms at: 20-Sep-2001 10:19

Hallvard Ystad wrote:

> ">> stats rebol
> You are not a member of list 'rebol' "

<<quoted lines omitted: 12>>

> 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".
Rebol has no rounding function. Here is routine that I have used forever, and
it makes a nice rebol one liner.
round-off: func [v [number!]][to-integer v + either v > 0 [.5][-.5]]

>
> 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.

Wow! Your not kidding! It crashes on me bigtime. Has anybody done a feedback?

> ~H
>
> Praetera censeo Carthaginem esse delendam
>
> --
> To unsubscribe from this list, please send an email to
>

**[rebol-request--rebol--com]**with "unsubscribe" in the > subject, without the quotes.--
Ryan Cole
Programmer Analyst
www.iesco-dms.com
707-468-5400

Notes

- Quoted lines have been omitted from some messages.

View the message alone to see the lines that have been omitted