1
1
mirror of https://github.com/wader/fq.git synced 2024-08-18 00:10:29 +03:00

bits: Add from_f32le, to_f32le, ...

TODO:
- show somehow generalize to/from encodings?
- move code to somwewhere else?
This commit is contained in:
Mattias Wadman 2023-08-03 15:10:38 +02:00
parent 496849daa5
commit e9226226d3
2 changed files with 88 additions and 0 deletions

View File

@ -2,14 +2,21 @@ package bits
import (
"embed"
"encoding/binary"
"fmt"
"math"
"github.com/wader/fq/format"
"github.com/wader/fq/internal/gojqx"
"github.com/wader/fq/internal/mathx"
"github.com/wader/fq/pkg/bitio"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/interp"
"github.com/wader/fq/pkg/scalar"
)
//go:embed bits.md
//go:embed bits.jq
//go:embed bytes.md
var bitsFS embed.FS
@ -39,5 +46,74 @@ func init() {
DecodeFn: decodeBits(8),
SkipDecodeFunction: true, // skip add bytes and frombytes function
})
interp.RegisterFunc2("_from_float", func(_ *interp.Interp, c any, nBits int, isLE bool) any {
switch nBits {
case 16, 32, 64:
default:
return fmt.Errorf("unsupported bit size %d, must be 16, 32 or 64", nBits)
}
br, err := interp.ToBitReader(c)
if err != nil {
return err
}
var b [8]byte
bs := b[:][0 : nBits/8]
_, err = br.ReadBits(bs[:], int64(nBits))
if err != nil {
return err
}
if isLE {
decode.ReverseBytes(bs[:])
}
switch nBits {
case 64:
return math.Float64frombits(binary.BigEndian.Uint64(bs[:]))
case 32:
return float64(math.Float32frombits(binary.BigEndian.Uint32(bs[:])))
case 16:
return float64(mathx.Float16(binary.BigEndian.Uint16(bs[:])).Float32())
default:
panic("unreachable")
}
})
interp.RegisterFunc2("_to_float", func(_ *interp.Interp, c any, nBits int, isLE bool) any {
switch nBits {
case 16, 32, 64:
default:
return fmt.Errorf("unsupported bit size %d, must be 16, 32 or 64", nBits)
}
v, ok := gojqx.Cast[float64](c)
if !ok {
return gojqx.FuncTypeError{Name: "_to_float", V: v}
}
var b [8]byte
bs := b[:][0 : nBits/8]
switch nBits {
case 64:
binary.BigEndian.PutUint64(bs, math.Float64bits(v))
case 32:
binary.BigEndian.PutUint32(bs, math.Float32bits(float32(v)))
case 16:
binary.BigEndian.PutUint16(bs, uint16(mathx.NewFloat16(float32(v))))
default:
panic("unreachable")
}
if isLE {
decode.ReverseBytes(bs[:])
}
br, err := interp.NewBinaryFromBitReader(bitio.NewBitReader(bs, -1), 8, 0)
if err != nil {
return err
}
return br
})
interp.RegisterFS(bitsFS)
}

12
format/bits/bits.jq Normal file
View File

@ -0,0 +1,12 @@
def from_f16be: _from_float(16; false);
def from_f32be: _from_float(32; false);
def from_f64be: _from_float(64; false);
def from_f16le: _from_float(16; true);
def from_f32le: _from_float(32; true);
def from_f64le: _from_float(64; true);
def to_f16le: _to_float(16; true);
def to_f32le: _to_float(32; true);
def to_f64le: _to_float(64; true);
def to_f16be: _to_float(16; false);
def to_f32be: _to_float(32; false);
def to_f64be: _to_float(64; false);