forked from filecoin-project/specs-actors
/
quantize.go
50 lines (41 loc) · 1.48 KB
/
quantize.go
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
package builtin
import "github.com/filecoin-project/go-state-types/abi"
// A spec for quantization.
type QuantSpec struct {
unit abi.ChainEpoch // The unit of quantization
offset abi.ChainEpoch // The offset from zero from which to base the modulus
}
func NewQuantSpec(unit, offset abi.ChainEpoch) QuantSpec {
return QuantSpec{unit: unit, offset: offset}
}
func (q QuantSpec) QuantizeUp(e abi.ChainEpoch) abi.ChainEpoch {
return QuantizeUp(e, q.unit, q.offset)
}
func (q QuantSpec) QuantizeDown(e abi.ChainEpoch) abi.ChainEpoch {
next := q.QuantizeUp(e)
// QuantizeDown == QuantizeUp iff e is a fixed point of QuantizeUp
if e == next {
return next
}
return next - q.unit
}
var NoQuantization = NewQuantSpec(1, 0)
// Rounds e to the nearest exact multiple of the quantization unit offset by
// offsetSeed % unit, rounding up.
// This function is equivalent to `unit * ceil(e - (offsetSeed % unit) / unit) + (offsetSeed % unit)`
// with the variables/operations are over real numbers instead of ints.
// Precondition: unit >= 0 else behaviour is undefined
func QuantizeUp(e abi.ChainEpoch, unit abi.ChainEpoch, offsetSeed abi.ChainEpoch) abi.ChainEpoch {
offset := offsetSeed % unit
remainder := (e - offset) % unit
quotient := (e - offset) / unit
// Don't round if epoch falls on a quantization epoch
if remainder == 0 {
return unit*quotient + offset
}
// Negative truncating division rounds up
if e-offset < 0 {
return unit*quotient + offset
}
return unit*(quotient+1) + offset
}