mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
gob: add support for complex numbers
R=rsc CC=golang-dev https://golang.org/cl/1708048
This commit is contained in:
parent
6d8b8101ea
commit
37a6bc838b
4 changed files with 224 additions and 69 deletions
|
|
@ -151,6 +151,11 @@ func ignoreUint(i *decInstr, state *decodeState, p unsafe.Pointer) {
|
|||
decodeUint(state)
|
||||
}
|
||||
|
||||
func ignoreTwoUints(i *decInstr, state *decodeState, p unsafe.Pointer) {
|
||||
decodeUint(state)
|
||||
decodeUint(state)
|
||||
}
|
||||
|
||||
func decBool(i *decInstr, state *decodeState, p unsafe.Pointer) {
|
||||
if i.indir > 0 {
|
||||
if *(*unsafe.Pointer)(p) == nil {
|
||||
|
|
@ -286,6 +291,20 @@ func floatFromBits(u uint64) float64 {
|
|||
return math.Float64frombits(v)
|
||||
}
|
||||
|
||||
func storeFloat32(i *decInstr, state *decodeState, p unsafe.Pointer) {
|
||||
v := floatFromBits(decodeUint(state))
|
||||
av := v
|
||||
if av < 0 {
|
||||
av = -av
|
||||
}
|
||||
// +Inf is OK in both 32- and 64-bit floats. Underflow is always OK.
|
||||
if math.MaxFloat32 < av && av <= math.MaxFloat64 {
|
||||
state.err = i.ovfl
|
||||
} else {
|
||||
*(*float32)(p) = float32(v)
|
||||
}
|
||||
}
|
||||
|
||||
func decFloat32(i *decInstr, state *decodeState, p unsafe.Pointer) {
|
||||
if i.indir > 0 {
|
||||
if *(*unsafe.Pointer)(p) == nil {
|
||||
|
|
@ -293,16 +312,7 @@ func decFloat32(i *decInstr, state *decodeState, p unsafe.Pointer) {
|
|||
}
|
||||
p = *(*unsafe.Pointer)(p)
|
||||
}
|
||||
v := floatFromBits(decodeUint(state))
|
||||
av := v
|
||||
if av < 0 {
|
||||
av = -av
|
||||
}
|
||||
if math.MaxFloat32 < av { // underflow is OK
|
||||
state.err = i.ovfl
|
||||
} else {
|
||||
*(*float32)(p) = float32(v)
|
||||
}
|
||||
storeFloat32(i, state, p)
|
||||
}
|
||||
|
||||
func decFloat64(i *decInstr, state *decodeState, p unsafe.Pointer) {
|
||||
|
|
@ -315,6 +325,30 @@ func decFloat64(i *decInstr, state *decodeState, p unsafe.Pointer) {
|
|||
*(*float64)(p) = floatFromBits(uint64(decodeUint(state)))
|
||||
}
|
||||
|
||||
// Complex numbers are just a pair of floating-point numbers, real part first.
|
||||
func decComplex64(i *decInstr, state *decodeState, p unsafe.Pointer) {
|
||||
if i.indir > 0 {
|
||||
if *(*unsafe.Pointer)(p) == nil {
|
||||
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex64))
|
||||
}
|
||||
p = *(*unsafe.Pointer)(p)
|
||||
}
|
||||
storeFloat32(i, state, p)
|
||||
storeFloat32(i, state, unsafe.Pointer(uintptr(p)+uintptr(unsafe.Sizeof(float(0)))))
|
||||
}
|
||||
|
||||
func decComplex128(i *decInstr, state *decodeState, p unsafe.Pointer) {
|
||||
if i.indir > 0 {
|
||||
if *(*unsafe.Pointer)(p) == nil {
|
||||
*(*unsafe.Pointer)(p) = unsafe.Pointer(new(complex128))
|
||||
}
|
||||
p = *(*unsafe.Pointer)(p)
|
||||
}
|
||||
real := floatFromBits(uint64(decodeUint(state)))
|
||||
imag := floatFromBits(uint64(decodeUint(state)))
|
||||
*(*complex128)(p) = cmplx(real, imag)
|
||||
}
|
||||
|
||||
// uint8 arrays are encoded as an unsigned count followed by the raw bytes.
|
||||
func decUint8Array(i *decInstr, state *decodeState, p unsafe.Pointer) {
|
||||
if i.indir > 0 {
|
||||
|
|
@ -540,21 +574,25 @@ func ignoreSlice(state *decodeState, elemOp decOp) os.Error {
|
|||
return ignoreArrayHelper(state, elemOp, int(decodeUint(state)))
|
||||
}
|
||||
|
||||
// Index by Go types.
|
||||
var decOpMap = []decOp{
|
||||
reflect.Bool: decBool,
|
||||
reflect.Int8: decInt8,
|
||||
reflect.Int16: decInt16,
|
||||
reflect.Int32: decInt32,
|
||||
reflect.Int64: decInt64,
|
||||
reflect.Uint8: decUint8,
|
||||
reflect.Uint16: decUint16,
|
||||
reflect.Uint32: decUint32,
|
||||
reflect.Uint64: decUint64,
|
||||
reflect.Float32: decFloat32,
|
||||
reflect.Float64: decFloat64,
|
||||
reflect.String: decString,
|
||||
reflect.Bool: decBool,
|
||||
reflect.Int8: decInt8,
|
||||
reflect.Int16: decInt16,
|
||||
reflect.Int32: decInt32,
|
||||
reflect.Int64: decInt64,
|
||||
reflect.Uint8: decUint8,
|
||||
reflect.Uint16: decUint16,
|
||||
reflect.Uint32: decUint32,
|
||||
reflect.Uint64: decUint64,
|
||||
reflect.Float32: decFloat32,
|
||||
reflect.Float64: decFloat64,
|
||||
reflect.Complex64: decComplex64,
|
||||
reflect.Complex128: decComplex128,
|
||||
reflect.String: decString,
|
||||
}
|
||||
|
||||
// Indexed by gob types. tComplex will be added during type.init().
|
||||
var decIgnoreOpMap = map[typeId]decOp{
|
||||
tBool: ignoreUint,
|
||||
tInt: ignoreUint,
|
||||
|
|
@ -652,6 +690,8 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId) (decOp, os.Error) {
|
|||
// Special cases
|
||||
wire := dec.wireType[wireId]
|
||||
switch {
|
||||
case wire == nil:
|
||||
panic("internal error: can't find ignore op for type " + wireId.string())
|
||||
case wire.arrayT != nil:
|
||||
elemId := wire.arrayT.Elem
|
||||
elemOp, err := dec.decIgnoreOpFor(elemId)
|
||||
|
|
@ -728,6 +768,8 @@ func (dec *Decoder) compatibleType(fr reflect.Type, fw typeId) bool {
|
|||
return fw == tUint
|
||||
case *reflect.FloatType:
|
||||
return fw == tFloat
|
||||
case *reflect.ComplexType:
|
||||
return fw == tComplex
|
||||
case *reflect.StringType:
|
||||
return fw == tString
|
||||
case *reflect.ArrayType:
|
||||
|
|
@ -866,39 +908,39 @@ func (dec *Decoder) decode(wireId typeId, e interface{}) os.Error {
|
|||
}
|
||||
|
||||
func init() {
|
||||
// We assume that the size of float is sufficient to tell us whether it is
|
||||
// equivalent to float32 or to float64. This is very unlikely to be wrong.
|
||||
var op decOp
|
||||
switch unsafe.Sizeof(float(0)) {
|
||||
case unsafe.Sizeof(float32(0)):
|
||||
op = decFloat32
|
||||
case unsafe.Sizeof(float64(0)):
|
||||
op = decFloat64
|
||||
var fop, cop decOp
|
||||
switch reflect.Typeof(float(0)).Bits() {
|
||||
case 32:
|
||||
fop = decFloat32
|
||||
cop = decComplex64
|
||||
case 64:
|
||||
fop = decFloat64
|
||||
cop = decComplex128
|
||||
default:
|
||||
panic("gob: unknown size of float")
|
||||
}
|
||||
decOpMap[reflect.Float] = op
|
||||
decOpMap[reflect.Float] = fop
|
||||
decOpMap[reflect.Complex] = cop
|
||||
|
||||
// A similar assumption about int and uint. Also assume int and uint have the same size.
|
||||
var uop decOp
|
||||
switch unsafe.Sizeof(int(0)) {
|
||||
case unsafe.Sizeof(int32(0)):
|
||||
op = decInt32
|
||||
var iop, uop decOp
|
||||
switch reflect.Typeof(int(0)).Bits() {
|
||||
case 32:
|
||||
iop = decInt32
|
||||
uop = decUint32
|
||||
case unsafe.Sizeof(int64(0)):
|
||||
op = decInt64
|
||||
case 64:
|
||||
iop = decInt64
|
||||
uop = decUint64
|
||||
default:
|
||||
panic("gob: unknown size of int/uint")
|
||||
}
|
||||
decOpMap[reflect.Int] = op
|
||||
decOpMap[reflect.Int] = iop
|
||||
decOpMap[reflect.Uint] = uop
|
||||
|
||||
// Finally uintptr
|
||||
switch unsafe.Sizeof(uintptr(0)) {
|
||||
case unsafe.Sizeof(uint32(0)):
|
||||
switch reflect.Typeof(uintptr(0)).Bits() {
|
||||
case 32:
|
||||
uop = decUint32
|
||||
case unsafe.Sizeof(uint64(0)):
|
||||
case 64:
|
||||
uop = decUint64
|
||||
default:
|
||||
panic("gob: unknown size of uintptr")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue