GoにいればGoに従え(31) math/bitsをTinyGoで使う、その2

Joseph Halfmoon

前回は、Goの標準ライブラリmath/bitsの中で、ビット・カウントとかローテイトとかバイナリ者には人気でも、一般ではあまり使われない操作を練習。今回はmath/bitsの残りを練習してみます。キャリー、ボロー付きの加減算、演算の前と後でビット幅が異なる乗算、除算です。アセンブラ書いていたら毎度お馴染みの者ども。

※「GoにいればGoに従え」Go関連記事の総Index

go標準ライブラリのmath/bitsの残り

標準ライブラリのmathの部の中でバイナリレベルの操作で必要なものどもを取り揃えているのがココです。解説ページが以下に。

Standard library > math > bits

既に前回ここの中でも「地味な」ものどもは練習済。今回練習するのは、符号無整数の加減乗除であります。わざわざライブラリ関数として加減乗除が用意されているのは、普通の加減乗除の演算子 + – * / などとは異なる部分があるからに違いありません。

    1. キャリー(桁上がり)付Add
    2. ボロー(桁借り)付Sub
    3. 乗算結果のビット幅が乗算前の倍幅になるMul
    4. 被除数が除数の倍のビット幅の割り算の 商と余り
    5. 上記の余りだけ求めるもの

という塩梅です。ビット幅は32ビット、64ビットと取り揃えられているのですが、今回練習してみるのは32ビット幅のみ。例によって手抜き。

今回実験のTinyGoソースコード

例によってさらっと撫でてみるだけの実験用のTinyGoコードが以下に。

package main

import (
    "fmt"
    "math/bits"
    "time"
)

func tstAdd32(inA uint32, inB uint32, carryIn uint32) {
    rslt, carryOut := bits.Add32(inA, inB, carryIn)
    fmt.Printf("Add32: 0x%08x + 0x%08x + %b -> 0x%08x , CO=%b\n", inA, inB, carryIn, rslt, carryOut)
}

func tstSub32(inA uint32, inB uint32, borrowIn uint32) {
    rslt, borrowOut := bits.Sub32(inA, inB, borrowIn)
    fmt.Printf("Sub32: 0x%08x - 0x%08x - %b -> 0x%08x , CO=%b\n", inA, inB, borrowIn, rslt, borrowOut)
}

func tstMul32(inA uint32, inB uint32) {
    Hi, Lo := bits.Mul32(inA, inB)
    fmt.Printf("Mul32: 0x%08x * 0x%08x -> 0x%08x_%08x\n", inA, inB, Hi, Lo)
}

func tstDiv32(dividendH uint32, dividendL uint32, divisor uint32) {
    quo, rem := bits.Div32(dividendH, dividendL, divisor)
    fmt.Printf("Div32: 0x%08x_%08x / %08x -> Quotient=0x%08x Remainder=0x%08x\n", dividendH, dividendL, divisor, quo, rem)
}

func tstRem32(dividendH uint32, dividendL uint32, divisor uint32) {
    rem := bits.Rem32(dividendH, dividendL, divisor)
    fmt.Printf("Rem32: 0x%08x_%08x / %08x -> Remainder=0x%08x\n", dividendH, dividendL, divisor, rem)
}

func main() {
    var tst uint8 = 0
    for {
        fmt.Println()
        tstAdd32(0x80000000, 0x7FFFFFFF, 0)
        tstAdd32(0x80000000, 0x7FFFFFFF, 1)
        tstSub32(1, 1, 0)
        tstSub32(1, 1, 1)
        tstMul32(0x80000000, 2)
        tstDiv32(0x1, 0x7FFFFFFF, 3)
        tstRem32(0x1, 0x7FFFFFFF, 3)
        if tst < 255 {
            tst++
        } else {
            tst = 0
        }
        time.Sleep(1000 * time.Millisecond)
    }
}
実験結果

さて、上記のソースをビルドしてUSB接続したターゲット機BBC micro:bit v2 に書き込むコマンドラインは以下です(該当のプロジェクトフォルダで。)

$ tinygo flash --target microbit-v2

シリアルモニタをmicro:bit に向けておけば、動作結果を観察することができます。その結果が以下に。bits2Results

キャリーにボローに、いろいろ計算できて良かった。

GoにいればGoに従え(30) math/bitsをTinyGoで使ってみる へ戻る

GoにいればGoに従え(32) math/cmplxをTinyGoで使う、ムムム早合点? へ進む