-
Notifications
You must be signed in to change notification settings - Fork 0
/
bitops.tcl
91 lines (76 loc) · 2.25 KB
/
bitops.tcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#return a mask grouped, conditional on the value of the previous mask.
#If number bits in a group going up, or the same (and of course NOT zero), the
#group is high. If number bits in the group go lower, the group goes low.
#
proc maskjoinif { oldmask oldermask divisor {masksize 16} } {
set newmask 0
set k 0
for { set i 0 } { $i < $masksize } {set i [expr $i+$divisor]} {
if { $oldmask == 0 } break
set oldbits 0
set olderbits 0
for { set j 0 } {$j <$divisor} {incr j} {
set oldbits [expr $oldbits + (($oldmask>>$j)&1)]
set olderbits [expr $olderbits + (($oldermask>>$j)&1)]
}
if { $oldbits > $olderbits } {
set newmask [expr $newmask|(1<<$k)]
} else {
if { $oldbits == $olderbits && $oldbits > 0 } {
set newmask [expr $newmask|(1<<$k)]
}
}
incr k
set oldmask [expr $oldmask >> $divisor]
set oldermask [expr $oldermask >> $divisor]
}
return $newmask
}
#return a mask with divided number of bits
proc maskjoin { oldmask divisor {masksize 16} } {
set newmask 0
set k 0
for { set i 0 } { $i < $masksize } {set i [expr $i+$divisor]} {
if { $oldmask == 0 } break
for { set j 0 } {$j <$divisor} {incr j} {
if { [expr $oldmask&(1<<$j)] } {
set newmask [expr $newmask|(1<<$k)]
break
}
}
incr k
set oldmask [expr $oldmask >> $divisor]
}
return $newmask
}
#return a mask with a greater number of bits
#note... masksize is the size of the INPUT mask.
#the output mask will be bigger by the multiplier.
proc masksplit { oldmask multiplier {masksize 16} } {
set newmask 0
set submask 0
for {set i 0} {$i<$multiplier} {incr i} {
set submask [expr $submask|(1<<$i)]
}
set k 0
for { set i 0 } { $i < $masksize } {incr i} {
if { $oldmask == 0 } break
if { [expr $oldmask&1] } {
set newmask [expr $newmask|($submask<<$k)]
}
set oldmask [expr $oldmask>>1]
set k [expr $k+$multiplier]
}
return $newmask
}
proc testsplit {{maxsplit 8}} {
for {set i 0} {$i<$maxsplit} {incr i} { puts "$i [masksplit $i 2]"}
}
proc testjoin {{maxjoin 8}} {
for {set i 0} {$i<$maxjoin} {incr i} { puts "$i [maskjoin $i 2]"}
}
proc testjoinif {oldermask {maxjoin 8}} {
for {set i 0} {$i<$maxjoin} {incr i} {
puts "$i [maskjoinif $i $oldermask 2]"
}
}