| 1 : |
dvdkhlng
|
1.1
|
\ Rewritten and improved bitmask code |
| 2 : |
|
|
|
| 3 : |
|
|
\ Author: David Kühling <dvdkhlng AT gmx DOT de> |
| 4 : |
|
|
\ Created: May 2010 |
| 5 : |
|
|
|
| 6 : |
|
|
\ Copyright (C) 2010 Free Software Foundation, Inc. |
| 7 : |
|
|
|
| 8 : |
|
|
\ This file is part of Gforth. |
| 9 : |
|
|
|
| 10 : |
|
|
\ Gforth is free software; you can redistribute it and/or |
| 11 : |
|
|
\ modify it under the terms of the GNU General Public License |
| 12 : |
|
|
\ as published by the Free Software Foundation, either version 3 |
| 13 : |
|
|
\ of the License, or (at your option) any later version. |
| 14 : |
|
|
|
| 15 : |
|
|
\ This program is distributed in the hope that it will be useful, |
| 16 : |
|
|
\ but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 : |
|
|
\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 : |
|
|
\ GNU General Public License for more details. |
| 19 : |
|
|
|
| 20 : |
|
|
\ You should have received a copy of the GNU General Public License |
| 21 : |
|
|
\ along with this program. If not, see http://www.gnu.org/licenses/. |
| 22 : |
|
|
|
| 23 : |
|
|
: bitset? ( x #bit -- flag ) \ get value of single bit in cell x |
| 24 : |
|
|
rshift 1 and ; |
| 25 : |
|
|
: setbit ( x1 0|1 #bit -- x2 ) \ set value of single bit in cell x |
| 26 : |
|
|
1 over lshift invert -rot \ mask for deleting bit |
| 27 : |
|
|
lshift \ mask for optionally setting bit |
| 28 : |
|
|
-rot and or ; \ first delete then optionally set bit |
| 29 : |
|
|
: (bits/cell) ( -- +n ) \ measure number of bits per cell |
| 30 : |
|
|
1 1 begin 1 lshift dup while |
| 31 : |
|
|
swap 1+ swap |
| 32 : |
|
|
repeat drop ; |
| 33 : |
|
|
(bits/cell) CONSTANT bits/cell |
| 34 : |
|
|
|
| 35 : |
|
|
: dispense ( x1-val x2-mask -- x3-masked ) |
| 36 : |
|
|
\ encode val into the bits given by mask. bits in mask can be spread out |
| 37 : |
|
|
\ as much as you like. for signed values 'val', first apply 'narrow' below |
| 38 : |
|
|
bits/cell 0 do \ iterate over bits in mask |
| 39 : |
|
|
dup i bitset? if \ if mask bit set: |
| 40 : |
|
|
over 1 and i setbit \ replace bit in mask by val's bit |
| 41 : |
|
|
swap 1 rshift swap \ and remove bit from val |
| 42 : |
|
|
then |
| 43 : |
|
|
loop |
| 44 : |
|
|
swap 0<> ABORT" dispense: value does not fit into masked bits" ; |
| 45 : |
|
|
: embed ( x1-accu x2-val x3-mask -- x4-result ) |
| 46 : |
|
|
\ encode 'val' into bits set given by mask, replacing corresponding bits in |
| 47 : |
|
|
\ 'accu' |
| 48 : |
|
|
dup >r dispense \ dispense value over masked bits |
| 49 : |
|
|
swap r> invert and \ delete corresponding bits in accu |
| 50 : |
|
|
or ; \ and add dispensed bits |
| 51 : |
|
|
|
| 52 : |
|
|
: mask ( +n -- mask ) \ get bitmask for lowest #n bits |
| 53 : |
|
|
0 invert swap lshift invert ; |
| 54 : |
|
|
: narrow ( n1 n2 -- x ) \ limit signed value to n2 bits |
| 55 : |
|
|
\ note: assumes 2-complement number n1 and 2-complement host |
| 56 : |
|
|
2dup mask and -rot \ compute masked value, |
| 57 : |
|
|
1- \ but before returning, check whether no bits lost |
| 58 : |
|
|
-1 over lshift ( lower bund) |
| 59 : |
|
|
1 rot lshift ( upper bound) |
| 60 : |
|
|
within 0= ABORT" narrow: signed value out of range" ; |
| 61 : |
|
|
|
| 62 : |
|
|
: maskinto ( "x-mask" -- runtime: x1-val x1-accu -- x2-masked ) |
| 63 : |
|
|
\ for backwards compatability with old bitmask code |
| 64 : |
|
|
]] swap [[ parse-word s>number drop ]]L embed [[ ; IMMEDIATE |