github.com/filecoin-project/specs-actors/v4@v4.0.2/actors/builtin/miner/quantize.go (about)

     1  package miner
     2  
     3  import "github.com/filecoin-project/go-state-types/abi"
     4  
     5  // A spec for quantization.
     6  type QuantSpec struct {
     7  	unit   abi.ChainEpoch // The unit of quantization
     8  	offset abi.ChainEpoch // The offset from zero from which to base the modulus
     9  }
    10  
    11  func NewQuantSpec(unit, offset abi.ChainEpoch) QuantSpec {
    12  	return QuantSpec{unit: unit, offset: offset}
    13  }
    14  
    15  func (q QuantSpec) QuantizeUp(e abi.ChainEpoch) abi.ChainEpoch {
    16  	return quantizeUp(e, q.unit, q.offset)
    17  }
    18  
    19  func (q QuantSpec) QuantizeDown(e abi.ChainEpoch) abi.ChainEpoch {
    20  	next := q.QuantizeUp(e)
    21  	// QuantizeDown == QuantizeUp iff e is a fixed point of QuantizeUp
    22  	if e == next {
    23  		return next
    24  	}
    25  	return next - q.unit
    26  }
    27  
    28  var NoQuantization = NewQuantSpec(1, 0)
    29  
    30  // Rounds e to the nearest exact multiple of the quantization unit offset by
    31  // offsetSeed % unit, rounding up.
    32  // This function is equivalent to `unit * ceil(e - (offsetSeed % unit) / unit) + (offsetSeed % unit)`
    33  // with the variables/operations are over real numbers instead of ints.
    34  // Precondition: unit >= 0 else behaviour is undefined
    35  func quantizeUp(e abi.ChainEpoch, unit abi.ChainEpoch, offsetSeed abi.ChainEpoch) abi.ChainEpoch {
    36  	offset := offsetSeed % unit
    37  
    38  	remainder := (e - offset) % unit
    39  	quotient := (e - offset) / unit
    40  	// Don't round if epoch falls on a quantization epoch
    41  	if remainder == 0 {
    42  		return unit*quotient + offset
    43  	}
    44  	// Negative truncating division rounds up
    45  	if e-offset < 0 {
    46  		return unit*quotient + offset
    47  	}
    48  	return unit*(quotient+1) + offset
    49  
    50  }