-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathdoublefloat.go
More file actions
116 lines (100 loc) · 3.01 KB
/
Copy pathdoublefloat.go
File metadata and controls
116 lines (100 loc) · 3.01 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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright (c) 2022, Peter Ohler, All rights reserved.
package slip
import (
"bytes"
"math/big"
"strconv"
)
// DoubleFloatSymbol is the symbol with a value of "doubleFloat".
const DoubleFloatSymbol = Symbol("double-float")
// DoubleFloat is a float64 Object.
type DoubleFloat float64
// String representation of the Object.
func (obj DoubleFloat) String() string {
return string(obj.Append([]byte{}))
}
// Append a buffer with a representation of the Object.
func (obj DoubleFloat) Append(b []byte) []byte {
return obj.Readably(b, &printer)
}
// Readably appends the object to a byte slice. If p.Readbly is true the
// objects is appended in a readable format otherwise a simple append which
// may or may not be readable.
func (obj DoubleFloat) Readably(b []byte, p *Printer) []byte {
// Use the LISP exponent nomenclature by forming the buffer and
// then replacing the 'e'.
var tmp []byte
switch {
case p.Readably:
// float64 precision is 16.
if p.Prec < 16 {
tmp = strconv.AppendFloat([]byte{}, float64(obj), 'e', p.Prec, 64)
} else {
tmp = strconv.AppendFloat([]byte{}, float64(obj), 'e', -1, 64)
}
b = append(b, bytes.ReplaceAll(bytes.ToLower(tmp), []byte{'e'}, []byte{'d'})...)
case p.Prec < 16:
b = strconv.AppendFloat(b, float64(obj), 'g', p.Prec, 64)
default:
tmp = strconv.AppendFloat([]byte{}, float64(obj), 'g', -1, 64)
b = append(b, bytes.ReplaceAll(bytes.ToLower(tmp), []byte{'e'}, []byte{'d'})...)
}
return b
}
// Simplify the Object into a float64.
func (obj DoubleFloat) Simplify() any {
return float64(obj)
}
// Equal returns true if this Object and the other are equal in value.
func (obj DoubleFloat) Equal(other Object) (eq bool) {
switch to := other.(type) {
case Fixnum:
eq = obj == DoubleFloat(to)
case Octet:
eq = obj == DoubleFloat(to)
case SingleFloat:
eq = float64(obj) == float64(to)
case DoubleFloat:
eq = obj == to
case *LongFloat:
eq = big.NewFloat(float64(obj)).Cmp((*big.Float)(to)) == 0
case *Ratio:
f, exact := (*big.Rat)(to).Float64()
eq = exact && f == float64(obj)
case *Bignum:
f := big.NewFloat(float64(obj))
if f.IsInt() {
i, _ := f.Int(nil)
eq = i.Cmp((*big.Int)(to)) == 0
}
}
return
}
// Hierarchy returns the class hierarchy as symbols for the instance.
func (obj DoubleFloat) Hierarchy() []Symbol {
return []Symbol{DoubleFloatSymbol, FloatSymbol, RealSymbol, NumberSymbol, TrueSymbol}
}
// FloatType returns 'double-float.
func (obj DoubleFloat) FloatType() Symbol {
return DoubleFloatSymbol
}
// RealType returns 'double-float.
func (obj DoubleFloat) RealType() Symbol {
return DoubleFloatSymbol
}
// NumberType returns 'double-float.
func (obj DoubleFloat) NumberType() Symbol {
return DoubleFloatSymbol
}
// Eval returns self.
func (obj DoubleFloat) Eval(s *Scope, depth int) Object {
return obj
}
// RealValue of the number as a float64.
func (obj DoubleFloat) RealValue() float64 {
return float64(obj)
}
// LoadForm returns a form that can be evaluated to create the object.
func (obj DoubleFloat) LoadForm() Object {
return obj
}