mirror of
https://github.com/hanzoai/volume.git
synced 2026-11-03 04:24:40 +00:00
A fork of Rancher's local-path-provisioner at v0.0.36. The behaviour is unchanged and deliberately so — a directory on the node a pod lands on is the right thing for a disk. What changes is identity. The provisioner answers to hanzo.ai/volume rather than rancher.io/local-path. That is not branding: two provisioners sharing one name race for the same claims, and a stock k3s carries the upstream one, so a cluster running both would settle our storage by chance. Data lives at /var/lib/hanzo/volume, so reading a Hanzo cluster does not mean learning another vendor's directory. Apache-2.0 as published, unaltered, with Rancher's attribution in NOTICE. The README says what this is not: durability. A volume here dies with its node. That is hanzoai/replicate's question, one layer up, and keeping the two apart is what lets the disk stay this simple.
146 lines
3.8 KiB
Go
146 lines
3.8 KiB
Go
package inf
|
|
|
|
import (
|
|
"math/big"
|
|
)
|
|
|
|
// Rounder represents a method for rounding the (possibly infinite decimal)
|
|
// result of a division to a finite Dec. It is used by Dec.Round() and
|
|
// Dec.Quo().
|
|
//
|
|
// See the Example for results of using each Rounder with some sample values.
|
|
//
|
|
type Rounder rounder
|
|
|
|
// See http://speleotrove.com/decimal/damodel.html#refround for more detailed
|
|
// definitions of these rounding modes.
|
|
var (
|
|
RoundDown Rounder // towards 0
|
|
RoundUp Rounder // away from 0
|
|
RoundFloor Rounder // towards -infinity
|
|
RoundCeil Rounder // towards +infinity
|
|
RoundHalfDown Rounder // to nearest; towards 0 if same distance
|
|
RoundHalfUp Rounder // to nearest; away from 0 if same distance
|
|
RoundHalfEven Rounder // to nearest; even last digit if same distance
|
|
)
|
|
|
|
// RoundExact is to be used in the case when rounding is not necessary.
|
|
// When used with Quo or Round, it returns the result verbatim when it can be
|
|
// expressed exactly with the given precision, and it returns nil otherwise.
|
|
// QuoExact is a shorthand for using Quo with RoundExact.
|
|
var RoundExact Rounder
|
|
|
|
type rounder interface {
|
|
|
|
// When UseRemainder() returns true, the Round() method is passed the
|
|
// remainder of the division, expressed as the numerator and denominator of
|
|
// a rational.
|
|
UseRemainder() bool
|
|
|
|
// Round sets the rounded value of a quotient to z, and returns z.
|
|
// quo is rounded down (truncated towards zero) to the scale obtained from
|
|
// the Scaler in Quo().
|
|
//
|
|
// When the remainder is not used, remNum and remDen are nil.
|
|
// When used, the remainder is normalized between -1 and 1; that is:
|
|
//
|
|
// -|remDen| < remNum < |remDen|
|
|
//
|
|
// remDen has the same sign as y, and remNum is zero or has the same sign
|
|
// as x.
|
|
Round(z, quo *Dec, remNum, remDen *big.Int) *Dec
|
|
}
|
|
|
|
type rndr struct {
|
|
useRem bool
|
|
round func(z, quo *Dec, remNum, remDen *big.Int) *Dec
|
|
}
|
|
|
|
func (r rndr) UseRemainder() bool {
|
|
return r.useRem
|
|
}
|
|
|
|
func (r rndr) Round(z, quo *Dec, remNum, remDen *big.Int) *Dec {
|
|
return r.round(z, quo, remNum, remDen)
|
|
}
|
|
|
|
var intSign = []*big.Int{big.NewInt(-1), big.NewInt(0), big.NewInt(1)}
|
|
|
|
func roundHalf(f func(c int, odd uint) (roundUp bool)) func(z, q *Dec, rA, rB *big.Int) *Dec {
|
|
return func(z, q *Dec, rA, rB *big.Int) *Dec {
|
|
z.Set(q)
|
|
brA, brB := rA.BitLen(), rB.BitLen()
|
|
if brA < brB-1 {
|
|
// brA < brB-1 => |rA| < |rB/2|
|
|
return z
|
|
}
|
|
roundUp := false
|
|
srA, srB := rA.Sign(), rB.Sign()
|
|
s := srA * srB
|
|
if brA == brB-1 {
|
|
rA2 := new(big.Int).Lsh(rA, 1)
|
|
if s < 0 {
|
|
rA2.Neg(rA2)
|
|
}
|
|
roundUp = f(rA2.Cmp(rB)*srB, z.UnscaledBig().Bit(0))
|
|
} else {
|
|
// brA > brB-1 => |rA| > |rB/2|
|
|
roundUp = true
|
|
}
|
|
if roundUp {
|
|
z.UnscaledBig().Add(z.UnscaledBig(), intSign[s+1])
|
|
}
|
|
return z
|
|
}
|
|
}
|
|
|
|
func init() {
|
|
RoundExact = rndr{true,
|
|
func(z, q *Dec, rA, rB *big.Int) *Dec {
|
|
if rA.Sign() != 0 {
|
|
return nil
|
|
}
|
|
return z.Set(q)
|
|
}}
|
|
RoundDown = rndr{false,
|
|
func(z, q *Dec, rA, rB *big.Int) *Dec {
|
|
return z.Set(q)
|
|
}}
|
|
RoundUp = rndr{true,
|
|
func(z, q *Dec, rA, rB *big.Int) *Dec {
|
|
z.Set(q)
|
|
if rA.Sign() != 0 {
|
|
z.UnscaledBig().Add(z.UnscaledBig(), intSign[rA.Sign()*rB.Sign()+1])
|
|
}
|
|
return z
|
|
}}
|
|
RoundFloor = rndr{true,
|
|
func(z, q *Dec, rA, rB *big.Int) *Dec {
|
|
z.Set(q)
|
|
if rA.Sign()*rB.Sign() < 0 {
|
|
z.UnscaledBig().Add(z.UnscaledBig(), intSign[0])
|
|
}
|
|
return z
|
|
}}
|
|
RoundCeil = rndr{true,
|
|
func(z, q *Dec, rA, rB *big.Int) *Dec {
|
|
z.Set(q)
|
|
if rA.Sign()*rB.Sign() > 0 {
|
|
z.UnscaledBig().Add(z.UnscaledBig(), intSign[2])
|
|
}
|
|
return z
|
|
}}
|
|
RoundHalfDown = rndr{true, roundHalf(
|
|
func(c int, odd uint) bool {
|
|
return c > 0
|
|
})}
|
|
RoundHalfUp = rndr{true, roundHalf(
|
|
func(c int, odd uint) bool {
|
|
return c >= 0
|
|
})}
|
|
RoundHalfEven = rndr{true, roundHalf(
|
|
func(c int, odd uint) bool {
|
|
return c > 0 || c == 0 && odd == 1
|
|
})}
|
|
}
|