gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

stream_float.go (2752B)


      1 package jsoniter
      2 
      3 import (
      4 	"fmt"
      5 	"math"
      6 	"strconv"
      7 )
      8 
      9 var pow10 []uint64
     10 
     11 func init() {
     12 	pow10 = []uint64{1, 10, 100, 1000, 10000, 100000, 1000000}
     13 }
     14 
     15 // WriteFloat32 write float32 to stream
     16 func (stream *Stream) WriteFloat32(val float32) {
     17 	if math.IsInf(float64(val), 0) || math.IsNaN(float64(val)) {
     18 		stream.Error = fmt.Errorf("unsupported value: %f", val)
     19 		return
     20 	}
     21 	abs := math.Abs(float64(val))
     22 	fmt := byte('f')
     23 	// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
     24 	if abs != 0 {
     25 		if float32(abs) < 1e-6 || float32(abs) >= 1e21 {
     26 			fmt = 'e'
     27 		}
     28 	}
     29 	stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 32)
     30 }
     31 
     32 // WriteFloat32Lossy write float32 to stream with ONLY 6 digits precision although much much faster
     33 func (stream *Stream) WriteFloat32Lossy(val float32) {
     34 	if math.IsInf(float64(val), 0) || math.IsNaN(float64(val)) {
     35 		stream.Error = fmt.Errorf("unsupported value: %f", val)
     36 		return
     37 	}
     38 	if val < 0 {
     39 		stream.writeByte('-')
     40 		val = -val
     41 	}
     42 	if val > 0x4ffffff {
     43 		stream.WriteFloat32(val)
     44 		return
     45 	}
     46 	precision := 6
     47 	exp := uint64(1000000) // 6
     48 	lval := uint64(float64(val)*float64(exp) + 0.5)
     49 	stream.WriteUint64(lval / exp)
     50 	fval := lval % exp
     51 	if fval == 0 {
     52 		return
     53 	}
     54 	stream.writeByte('.')
     55 	for p := precision - 1; p > 0 && fval < pow10[p]; p-- {
     56 		stream.writeByte('0')
     57 	}
     58 	stream.WriteUint64(fval)
     59 	for stream.buf[len(stream.buf)-1] == '0' {
     60 		stream.buf = stream.buf[:len(stream.buf)-1]
     61 	}
     62 }
     63 
     64 // WriteFloat64 write float64 to stream
     65 func (stream *Stream) WriteFloat64(val float64) {
     66 	if math.IsInf(val, 0) || math.IsNaN(val) {
     67 		stream.Error = fmt.Errorf("unsupported value: %f", val)
     68 		return
     69 	}
     70 	abs := math.Abs(val)
     71 	fmt := byte('f')
     72 	// Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
     73 	if abs != 0 {
     74 		if abs < 1e-6 || abs >= 1e21 {
     75 			fmt = 'e'
     76 		}
     77 	}
     78 	stream.buf = strconv.AppendFloat(stream.buf, float64(val), fmt, -1, 64)
     79 }
     80 
     81 // WriteFloat64Lossy write float64 to stream with ONLY 6 digits precision although much much faster
     82 func (stream *Stream) WriteFloat64Lossy(val float64) {
     83 	if math.IsInf(val, 0) || math.IsNaN(val) {
     84 		stream.Error = fmt.Errorf("unsupported value: %f", val)
     85 		return
     86 	}
     87 	if val < 0 {
     88 		stream.writeByte('-')
     89 		val = -val
     90 	}
     91 	if val > 0x4ffffff {
     92 		stream.WriteFloat64(val)
     93 		return
     94 	}
     95 	precision := 6
     96 	exp := uint64(1000000) // 6
     97 	lval := uint64(val*float64(exp) + 0.5)
     98 	stream.WriteUint64(lval / exp)
     99 	fval := lval % exp
    100 	if fval == 0 {
    101 		return
    102 	}
    103 	stream.writeByte('.')
    104 	for p := precision - 1; p > 0 && fval < pow10[p]; p-- {
    105 		stream.writeByte('0')
    106 	}
    107 	stream.WriteUint64(fval)
    108 	for stream.buf[len(stream.buf)-1] == '0' {
    109 		stream.buf = stream.buf[:len(stream.buf)-1]
    110 	}
    111 }