Skip to content

Commit 4d8b26a

Browse files
authored
Merge pull request #868 from devlights/add-bitvector-example
2 parents 32229a4 + 5448f09 commit 4d8b26a

File tree

3 files changed

+265
-0
lines changed

3 files changed

+265
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# https://taskfile.dev
2+
3+
version: '3'
4+
5+
tasks:
6+
default:
7+
cmds:
8+
- go run .
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
)
7+
8+
type (
9+
// BitVector は、ビットベクタを表す構造体です.
10+
BitVector struct {
11+
bits []uint32
12+
size int
13+
}
14+
kind int
15+
)
16+
17+
const (
18+
AND kind = iota
19+
OR kind = iota
20+
XOR kind = iota
21+
)
22+
23+
// NewBitVector は、指定されたサイズのビットベクタを作成します.
24+
func NewBitVector(size int) *BitVector {
25+
return &BitVector{
26+
bits: make([]uint32, (size+31)/32),
27+
size: size,
28+
}
29+
}
30+
31+
// Set は、指定されたインデックス位置のビットを設定します.
32+
func (me *BitVector) Set(index int, value bool) error {
33+
if index < 0 || index >= me.size {
34+
return fmt.Errorf("index out of range: %d", index)
35+
}
36+
37+
var (
38+
aryIndex = index / 32
39+
bitIndex = uint(index % 32)
40+
)
41+
if value {
42+
me.bits[aryIndex] |= 1 << bitIndex // ビットオン (OR)
43+
} else {
44+
me.bits[aryIndex] &^= 1 << bitIndex // ビットクリア (AND NOT)
45+
}
46+
47+
return nil
48+
}
49+
50+
// Get は、指定されたインデックス位置のビットを取得します.
51+
func (me *BitVector) Get(index int) (bool, error) {
52+
if index < 0 || index >= me.size {
53+
return false, fmt.Errorf("index out of range: %d", index)
54+
}
55+
56+
var (
57+
aryIndex = index / 32
58+
bitIndex = uint(index % 32)
59+
bit = (me.bits[aryIndex] & (1 << bitIndex)) != 0
60+
)
61+
62+
return bit, nil
63+
}
64+
65+
// And は、指定された *BitVector とのAND結果を設定した新たな *BitVector を返します.
66+
func (me *BitVector) And(other *BitVector) (*BitVector, error) {
67+
return me.calc(other, AND)
68+
}
69+
70+
// Or は、指定された *BitVector とのOR結果を設定した新たな *BitVector を返します.
71+
func (me *BitVector) Or(other *BitVector) (*BitVector, error) {
72+
return me.calc(other, OR)
73+
}
74+
75+
// Xor は、指定された *BitVector とのXOR結果を設定した新たな *BitVector を返します.
76+
func (me *BitVector) Xor(other *BitVector) (*BitVector, error) {
77+
return me.calc(other, XOR)
78+
}
79+
80+
func (me *BitVector) calc(other *BitVector, op kind) (*BitVector, error) {
81+
if me.size != other.size {
82+
return nil, fmt.Errorf("size mismatch: %d != %d", me.size, other.size)
83+
}
84+
85+
var (
86+
result = NewBitVector(me.size)
87+
arySize = (me.size + 31) / 32
88+
)
89+
for i := range arySize {
90+
switch op {
91+
case AND:
92+
result.bits[i] = me.bits[i] & other.bits[i]
93+
case OR:
94+
result.bits[i] = me.bits[i] | other.bits[i]
95+
case XOR:
96+
result.bits[i] = me.bits[i] ^ other.bits[i]
97+
default:
98+
return nil, fmt.Errorf("unknown kind: %d", op)
99+
}
100+
}
101+
102+
return result, nil
103+
}
104+
105+
// String は、ビットベクタの文字列表現を返します.
106+
func (me *BitVector) String() string {
107+
var (
108+
sb strings.Builder
109+
val bool
110+
)
111+
for i := range me.size {
112+
val, _ = me.Get(i)
113+
if val {
114+
sb.WriteRune('1')
115+
} else {
116+
sb.WriteRune('0')
117+
}
118+
}
119+
120+
return sb.String()
121+
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"errors"
6+
"log"
7+
"time"
8+
)
9+
10+
const (
11+
MainTimeout = 100 * time.Millisecond
12+
ProcTimeout = 500 * time.Microsecond
13+
)
14+
15+
var (
16+
ErrMainTooSlow = errors.New("[MAIN] TOO SLOW")
17+
ErrProcTooSlow = errors.New("[PROC] TOO SLOW")
18+
)
19+
20+
func init() {
21+
log.SetFlags(0)
22+
}
23+
24+
func main() {
25+
var (
26+
rootCtx = context.Background()
27+
mainCtx, mainCxl = context.WithTimeoutCause(rootCtx, MainTimeout, ErrMainTooSlow)
28+
procCtx = run(mainCtx)
29+
err error
30+
)
31+
defer mainCxl()
32+
33+
select {
34+
case <-mainCtx.Done():
35+
err = context.Cause(mainCtx)
36+
case <-procCtx.Done():
37+
if err = context.Cause(procCtx); errors.Is(err, context.Canceled) {
38+
err = nil
39+
}
40+
}
41+
42+
if err != nil {
43+
log.Fatal(err)
44+
}
45+
}
46+
47+
func run(pCtx context.Context) context.Context {
48+
var (
49+
ctx, cxl = context.WithCancelCause(pCtx)
50+
)
51+
52+
go func() {
53+
cxl(proc(ctx))
54+
}()
55+
go func() {
56+
<-time.After(ProcTimeout)
57+
cxl(ErrProcTooSlow)
58+
}()
59+
60+
return ctx
61+
}
62+
63+
func proc(_ context.Context) error {
64+
const (
65+
bitSize = 32
66+
)
67+
68+
//
69+
// ビットの設定
70+
//
71+
var (
72+
bv = NewBitVector(bitSize)
73+
err error
74+
)
75+
76+
for _, i := range []int{1, 3, 23} {
77+
if err = bv.Set(i, true); err != nil {
78+
return err
79+
}
80+
}
81+
log.Printf("ORIG : %s", bv)
82+
83+
//
84+
// ビットの取得
85+
//
86+
var (
87+
bits []bool
88+
bit bool
89+
)
90+
91+
for _, i := range []int{1, 2, 3, 4} {
92+
if bit, err = bv.Get(i); err != nil {
93+
return err
94+
}
95+
96+
bits = append(bits, bit)
97+
}
98+
log.Printf("BITS : %v", bits)
99+
100+
//
101+
// 別のビットベクタとの演算
102+
//
103+
var (
104+
bv2 = NewBitVector(bitSize)
105+
bvAnd *BitVector
106+
bvOr *BitVector
107+
bvXor *BitVector
108+
)
109+
110+
for _, i := range []int{2, 23, 24} {
111+
if err = bv2.Set(i, true); err != nil {
112+
return err
113+
}
114+
}
115+
log.Printf("OTHER: %s", bv2)
116+
117+
// AND
118+
if bvAnd, err = bv.And(bv2); err != nil {
119+
return err
120+
}
121+
log.Printf("AND : %s", bvAnd)
122+
123+
// OR
124+
if bvOr, err = bv.Or(bv2); err != nil {
125+
return err
126+
}
127+
log.Printf("OR : %s", bvOr)
128+
129+
// XOR
130+
if bvXor, err = bv.Xor(bv2); err != nil {
131+
return err
132+
}
133+
log.Printf("XOR : %s", bvXor)
134+
135+
return nil
136+
}

0 commit comments

Comments
 (0)