forked from cue-lang/libcue
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfloat.go
More file actions
55 lines (43 loc) · 1.11 KB
/
Copy pathfloat.go
File metadata and controls
55 lines (43 loc) · 1.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package main
/*
#include <stdint.h>
#include <stdbool.h>
#include "cue.h"
*/
import "C"
import "math/big"
func ToCueFloat(x *big.Float, out *C.cue_float) {
if x == nil {
panic("big.Float value is nil")
}
if x.Sign() == 0 {
out.exponent = 0
out.sign = false
out.mantissa_len = 1
out.mantissa = C.CBytes([]byte{0})
return
}
// precision in bits of mantissa
prec := x.Prec()
// frac = normalized fraction (0.5 < |frac| < 1), so x = frac * 2^exp
var frac big.Float
bigFloatExp := x.MantExp(&frac)
// frac = frac * 2^prec, so that frac is now an integer
frac.SetMantExp(&frac, int(prec))
// since it is an integer, fetch it
mantissa, _ := frac.Int(nil)
// Cue does not support infinity values (failed arithmetic: division by zero)
if mantissa == nil {
panic("infinity value in Cue")
}
// separate sign from mantissa
isNegative := mantissa.Sign() < 0
mantissa.Abs(mantissa)
// Absolute value, big-endian.
b := mantissa.Bytes()
exp := int64(bigFloatExp) - int64(prec)
out.exponent = C.int64_t(exp)
out.sign = C.bool(isNegative)
out.mantissa_len = C.size_t(len(b))
out.mantissa = C.CBytes(b)
}