Compare commits
No commits in common. "5b437644bd67116d6b4360776bc2ea964270bcc3" and "c4029042e01957f38567ca887e9146a3e28c4992" have entirely different histories.
5b437644bd
...
c4029042e0
|
@ -0,0 +1,502 @@
|
||||||
|
package number
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
"gitea.zaclys.com/bvaudour/gob/option"
|
||||||
|
)
|
||||||
|
|
||||||
|
type atom struct {
|
||||||
|
number option.Option[*big.Rat]
|
||||||
|
sign int
|
||||||
|
}
|
||||||
|
|
||||||
|
func undefined[S integer | float](sign S) atom {
|
||||||
|
out := atom{
|
||||||
|
sign: signOf(sign),
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.format()
|
||||||
|
}
|
||||||
|
|
||||||
|
func rational[S integer | float](rat *big.Rat, sign ...S) atom {
|
||||||
|
s := 1
|
||||||
|
if len(sign) > 0 {
|
||||||
|
s = signOf(sign[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
out := atom{
|
||||||
|
number: option.Some(rat),
|
||||||
|
sign: s,
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.format()
|
||||||
|
}
|
||||||
|
|
||||||
|
func frac0[S integer | float](num, denom *big.Int, sign ...S) atom {
|
||||||
|
if denom.IsInt64() && denom.Int64() == 0 {
|
||||||
|
s := num.Sign()
|
||||||
|
if len(sign) > 0 {
|
||||||
|
s *= signOf(sign[0])
|
||||||
|
}
|
||||||
|
return undefined(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
rat := new(big.Rat).SetFrac(num, denom)
|
||||||
|
return rational(rat, sign...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func frac[N integer | float, S integer | float](num, denom N, sign ...S) atom {
|
||||||
|
if denom == 0 {
|
||||||
|
s := signOf(num)
|
||||||
|
if len(sign) > 0 {
|
||||||
|
s *= signOf(sign[0])
|
||||||
|
}
|
||||||
|
return undefined(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
rat := new(big.Rat).SetFrac64(int64(num), int64(denom))
|
||||||
|
return rational(rat, sign...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func entire0[S integer | float](n *big.Int, sign ...S) atom {
|
||||||
|
rat := new(big.Rat).SetInt(n)
|
||||||
|
|
||||||
|
return rational(rat, sign...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func entire[N integer | float, S integer | float](n N, sign ...S) atom {
|
||||||
|
rat := new(big.Rat).SetInt64(int64(n))
|
||||||
|
|
||||||
|
return rational(rat, sign...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func decimal[N integer | float, S integer | float](n N, sign ...S) atom {
|
||||||
|
rat := new(big.Rat).SetFloat64(float64(n))
|
||||||
|
|
||||||
|
return rational(rat, sign...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pow[B integer | float, P integer | float](base B, precision ...P) atom {
|
||||||
|
p := FloatingPrecision
|
||||||
|
if len(precision) > 0 {
|
||||||
|
p = uint64(precision[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
a := entire(formatBase(base), 1)
|
||||||
|
return a.pow(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) get() (*big.Rat, bool) {
|
||||||
|
return a.number.Get()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *atom) format() atom {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
a.sign *= nb.Sign()
|
||||||
|
nb.Abs(nb)
|
||||||
|
}
|
||||||
|
|
||||||
|
a.sign = signOf(a.sign)
|
||||||
|
return *a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) clone(format ...bool) atom {
|
||||||
|
out := atom{
|
||||||
|
sign: a.sign,
|
||||||
|
}
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
out.number = option.Some(new(big.Rat).Set(nb))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(format) > 0 && format[0] {
|
||||||
|
return out.format()
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) rat() (nb *big.Rat, ok bool) {
|
||||||
|
if nb, ok = a.get(); ok {
|
||||||
|
nb = new(big.Rat).Set(nb)
|
||||||
|
if a.sign < 0 {
|
||||||
|
nb.Neg(nb)
|
||||||
|
} else if a.sign == 0 {
|
||||||
|
nb.SetInt64(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) Sign() int {
|
||||||
|
return a.sign
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) IsNeg() bool {
|
||||||
|
return a.Sign() < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) IsPos() bool {
|
||||||
|
return !a.IsNeg()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) IsZero() bool {
|
||||||
|
return a.Is(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) neg() atom {
|
||||||
|
out := a.clone()
|
||||||
|
out.sign = -out.sign
|
||||||
|
|
||||||
|
return out.format()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) abs() atom {
|
||||||
|
out := a.clone()
|
||||||
|
if out.sign < 0 {
|
||||||
|
out.sign = -out.sign
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.format()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) IsDefined() bool {
|
||||||
|
return a.number.IsDefined()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) IsInf() bool {
|
||||||
|
return !a.IsDefined() && a.Sign() > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) IsNegInf() bool {
|
||||||
|
return !a.IsDefined() && a.Sign() < 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) IsNan() bool {
|
||||||
|
return !a.IsDefined() && a.Sign() == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) Is(i int64) bool {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
return nb.IsInt() && nb.Num().Int64()*int64(a.Sign()) == i
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) IsFloat(f float64) bool {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
e, ok := nb.Float64()
|
||||||
|
return ok && e*float64(a.Sign()) == f
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) isInt() bool {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
return nb.IsInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) isInt64() bool {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
return nb.IsInt() && nb.Num().IsInt64()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) toInt64() (n int64, ok bool) {
|
||||||
|
var nb *big.Rat
|
||||||
|
if nb, ok = a.get(); ok {
|
||||||
|
if nb.IsInt() {
|
||||||
|
if num := nb.Num(); num.IsInt64() {
|
||||||
|
n = num.Int64()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *atom) setInt() atom {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
nb.SetInt(new(big.Int).Quo(nb.Num(), nb.Denom()))
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.format()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) num() atom {
|
||||||
|
if a.Sign() == 0 {
|
||||||
|
return entire(0, 0)
|
||||||
|
} else if nb, ok := a.get(); ok {
|
||||||
|
return entire0(nb.Num(), a.Sign())
|
||||||
|
}
|
||||||
|
|
||||||
|
return entire(a.Sign(), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) denom() atom {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
return entire0(nb.Denom(), 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return entire(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a1 atom) cmp(a2 atom) int {
|
||||||
|
if a1.IsNan() {
|
||||||
|
if a2.IsNan() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return -2
|
||||||
|
} else if a2.IsNan() {
|
||||||
|
return 2
|
||||||
|
} else if nb1, ok := a1.rat(); ok {
|
||||||
|
if nb2, ok := a2.rat(); ok {
|
||||||
|
return nb1.Cmp(nb2)
|
||||||
|
}
|
||||||
|
return -a2.Sign()
|
||||||
|
} else if a2.IsDefined() {
|
||||||
|
return a1.Sign()
|
||||||
|
}
|
||||||
|
|
||||||
|
return compare(a1.Sign(), a2.Sign())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a1 atom) add(a2 atom) atom {
|
||||||
|
if r1, ok := a1.rat(); ok {
|
||||||
|
if r2, ok := a2.rat(); ok {
|
||||||
|
return rational(new(big.Rat).Add(r1, r2), 1)
|
||||||
|
}
|
||||||
|
return a2.clone()
|
||||||
|
} else if a2.IsDefined() || a1.Sign() == a2.Sign() {
|
||||||
|
return undefined(a1.Sign())
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a1 atom) sub(a2 atom) atom {
|
||||||
|
return a1.add(a2.neg())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) inc() atom {
|
||||||
|
return a.add(entire(1, 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) dec() atom {
|
||||||
|
return a.sub(entire(1, 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a1 atom) mul(a2 atom) atom {
|
||||||
|
s := a1.Sign() * a2.Sign()
|
||||||
|
if nb1, ok := a1.get(); ok {
|
||||||
|
if nb2, ok := a2.get(); ok {
|
||||||
|
return rational(new(big.Rat).Mul(nb1, nb2), s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a1 atom) div(a2 atom) atom {
|
||||||
|
if nb1, ok := a1.get(); ok {
|
||||||
|
if nb2, ok := a2.get(); ok {
|
||||||
|
if nb2.IsInt() && nb2.Num().IsInt64() && nb2.Num().Int64() == 0 {
|
||||||
|
return undefined(0)
|
||||||
|
}
|
||||||
|
return rational(new(big.Rat).Quo(nb1, nb2), a1.Sign()*a2.Sign())
|
||||||
|
}
|
||||||
|
return undefined(a1.Sign() * a2.Sign())
|
||||||
|
} else if a2.IsDefined() {
|
||||||
|
return undefined(a1.Sign() * a2.Sign())
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a1 atom) quo(a2 atom) atom {
|
||||||
|
if nb1, ok := a1.get(); ok {
|
||||||
|
if nb2, ok := a2.get(); ok {
|
||||||
|
if nb2.IsInt() && nb2.Num().IsInt64() && nb2.Num().Int64() == 0 {
|
||||||
|
return undefined(0)
|
||||||
|
}
|
||||||
|
n := new(big.Int).Mul(nb1.Num(), nb2.Num())
|
||||||
|
d := new(big.Int).Mul(nb1.Denom(), nb2.Denom())
|
||||||
|
return entire0(new(big.Int).Quo(n, d), a1.Sign()*a2.Sign())
|
||||||
|
}
|
||||||
|
return undefined(a1.Sign() * a2.Sign())
|
||||||
|
} else if a2.IsDefined() {
|
||||||
|
return undefined(a1.Sign() * a2.Sign())
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a1 atom) quoRem(a2 atom) (q, r atom) {
|
||||||
|
q = a1.quo(a2)
|
||||||
|
r = a1.sub(a2.mul(q))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a1 atom) rem(a2 atom) atom {
|
||||||
|
_, r := a1.quoRem(a2)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) inv() atom {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
n, d := nb.Num(), nb.Denom()
|
||||||
|
return frac0(d, n, a.Sign())
|
||||||
|
}
|
||||||
|
|
||||||
|
if a.Sign() == 0 {
|
||||||
|
return undefined(0)
|
||||||
|
}
|
||||||
|
return entire(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) pow(p uint64) atom {
|
||||||
|
switch {
|
||||||
|
case p == 0:
|
||||||
|
if a.IsNan() {
|
||||||
|
return undefined(0)
|
||||||
|
}
|
||||||
|
return entire(0, 0)
|
||||||
|
case p == 1:
|
||||||
|
return a.clone(true)
|
||||||
|
case p == 2:
|
||||||
|
return a.mul(a)
|
||||||
|
case p&1 == 0:
|
||||||
|
return a.mul(a).pow(p >> 1)
|
||||||
|
default:
|
||||||
|
return a.mul(a).pow(p >> 1).mul(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) optimize(precision atom) atom {
|
||||||
|
if a.isInt() || !a.IsDefined() {
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
n1, d1 := a.num().abs(), a.denom()
|
||||||
|
t := n1.mul(precision).quo(d1)
|
||||||
|
an := t.div(precision)
|
||||||
|
n2, d2 := an.num(), an.denom()
|
||||||
|
if n2.cmp(n1) < 0 || d2.cmp(d1) < 0 {
|
||||||
|
t.sign = a.sign
|
||||||
|
return t.format()
|
||||||
|
}
|
||||||
|
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) heron(n uint64, tmp atom) atom {
|
||||||
|
n0 := entire(int64(n), 1)
|
||||||
|
n1 := n0.dec()
|
||||||
|
|
||||||
|
return ((tmp.mul(n1)).add(a.div(tmp.pow(n - 1)))).div(n0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) sqrtn(n uint64, base uint) atom {
|
||||||
|
switch {
|
||||||
|
case a.IsNan() || n < 2 || (a.IsNeg() && n&1 == 0):
|
||||||
|
return undefined(0)
|
||||||
|
case a.IsZero() || a.Is(1) || !a.IsDefined():
|
||||||
|
return a.clone(true)
|
||||||
|
default:
|
||||||
|
precision := pow(base, FloatingPrecision)
|
||||||
|
pi := precision.inv()
|
||||||
|
out := a.heron(n, a).optimize(precision)
|
||||||
|
for {
|
||||||
|
t := a.heron(n, out).optimize(precision)
|
||||||
|
if out.cmp(t) == 0 {
|
||||||
|
break
|
||||||
|
} else if out.sub(t).abs().cmp(pi) < 0 {
|
||||||
|
out = t
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) IsEven() bool {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
return nb.IsInt() && nb.Num().Bit(0) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) IsOdd() bool {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
return nb.IsInt() && nb.Num().Bit(0) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) lsh(n uint) atom {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
if nb.IsInt() {
|
||||||
|
num, denom := new(big.Int).Lsh(nb.Num(), n), nb.Denom()
|
||||||
|
return frac0(num, denom, a.Sign())
|
||||||
|
}
|
||||||
|
return a.mul(pow(2, n))
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined(a.Sign())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) rsh(n uint) atom {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
if nb.IsInt() {
|
||||||
|
num, denom := new(big.Int).Rsh(nb.Num(), n), nb.Denom()
|
||||||
|
return frac0(num, denom, a.Sign())
|
||||||
|
}
|
||||||
|
return a.div(pow(2, n))
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined(a.Sign())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) len(base uint) int {
|
||||||
|
if nb, ok := a.get(); ok {
|
||||||
|
if !nb.IsInt() {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
num := nb.Num()
|
||||||
|
if num.IsInt64() && num.Int64() == 0 {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
s := num.Text(int(base))
|
||||||
|
return len(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a atom) bit(n uint64, base uint) int {
|
||||||
|
if !a.isInt() {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
out := a
|
||||||
|
if n > 0 {
|
||||||
|
out = a.quo(pow(base, n))
|
||||||
|
}
|
||||||
|
|
||||||
|
out = out.rem(entire(base, 1))
|
||||||
|
if nb, ok := out.get(); ok {
|
||||||
|
return int(nb.Num().Int64())
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
|
@ -7,56 +7,42 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
FloatingPrecision uint64 = 10 // Nombre de chiffres après la virgule pour un nombre décimal ou un nombre scientifique
|
FloatingPrecision uint64 = 10 // Nombre de chiffres après la virgule pour un nombre décimal ou un nombre scientifique
|
||||||
FixedPrecision = false // Si vrai le nombre de chiffres après la virgule est fixe.
|
FixedPrecision = false // Si vrai le nombre chiffre après la virgule est fixe.
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
rSign = `(\+|-)`
|
regSign = `\+|-`
|
||||||
rBSign = `(0|1)`
|
regBSign = `0|1`
|
||||||
rNb2 = `(0|1)`
|
regBase = `\(\d+\)`
|
||||||
rNb8 = `[0-7]`
|
regBase2 = `B|b`
|
||||||
rNb10 = `\d`
|
regBase8 = `O|o`
|
||||||
rNb16 = `[0-9a-fA-F]`
|
regBase16 = `X|x`
|
||||||
rNbN = `[0-9a-zA-Z]`
|
regNb = `[0-9a-zA-Z]`
|
||||||
rBase2 = `(B|b)`
|
regNb2 = `0|1`
|
||||||
rBase8 = `(O|o)`
|
regNb8 = `[0-7]`
|
||||||
rBase16 = `(X|x)`
|
regNb10 = `\d`
|
||||||
rExp10 = `E|e`
|
regNb16 = `[0-9a-fA-F]`
|
||||||
rExpN = `×\d+\^`
|
regExp = `×\d+\^`
|
||||||
|
regExp10 = `E|e`
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rInt2 = fmt.Sprintf(`(%s)%s+`, rBase2, rNb2)
|
regInt = regexp.MustCompile(fmt.Sprintf(`%s(%s)?%s+`, regBase, regSign, regNb))
|
||||||
rInt8 = fmt.Sprintf(`(%s)%s+`, rBase8, rNb8)
|
regInt2 = regexp.MustCompile(fmt.Sprintf(`(%s)(%s)(%s)+`, regBSign, regBase2, regNb2))
|
||||||
rInt10 = fmt.Sprintf(`(%s)%s+`, rSign, rNb10)
|
regInt8 = regexp.MustCompile(fmt.Sprintf(`(%s)(%s)(%s)+`, regBSign, regBase8, regNb8))
|
||||||
rInt16 = fmt.Sprintf(`(%s)%s+`, rBase8, rNb8)
|
regInt10 = regexp.MustCompile(fmt.Sprintf(`(%s)?%s+`, regSign, regNb10))
|
||||||
rIntN = fmt.Sprintf(`\(%s+\)%s?%s+`, rNb10, rSign, rNbN)
|
regInt16 = regexp.MustCompile(fmt.Sprintf(`(%s)(%s)(%s)+`, regBSign, regBase16, regNb16))
|
||||||
rIntB = fmt.Sprintf(`%s(%s|%s|%s)`, rBSign, rInt2, rInt8, rInt16)
|
|
||||||
rInt = fmt.Sprintf(`(%s|%s|%s)`, rInt10, rIntN, rIntB)
|
|
||||||
|
|
||||||
rDec2 = fmt.Sprintf(`(%s)(%s+\.%s*|\.%s+)`, rBase2, rNb2, rNb2, rNb2)
|
regDec = regexp.MustCompile(fmt.Sprintf(`%s(%s)?(%s*\.%s+|%s+\.)`, regBase, regSign, regNb, regNb, regNb))
|
||||||
rDec8 = fmt.Sprintf(`(%s)(%s+\.%s*|\.%s+)`, rBase8, rNb8, rNb8, rNb8)
|
regDec2 = regexp.MustCompile(fmt.Sprintf(`(%s)(%s)((%s)*\.(%s)+|(%s)+\.)`, regBSign, regBase2, regNb2, regNb2, regNb2))
|
||||||
rDec10 = fmt.Sprintf(`%s?(%s+\.%s*|\.%s+)`, rSign, rNb10, rNb10, rNb10)
|
regDec8 = regexp.MustCompile(fmt.Sprintf(`(%s)(%s)((%s)*\.(%s)+|(%s)+\.)`, regBSign, regBase8, regNb8, regNb8, regNb8))
|
||||||
rDec16 = fmt.Sprintf(`(%s)(%s+\.%s*|\.%s+)`, rBase16, rNb16, rNb16, rNb16)
|
regDec10 = regexp.MustCompile(fmt.Sprintf(`(%s)?(%s*\.%s+|%s+\.)`, regSign, regNb10, regNb10, regNb10))
|
||||||
rDecN = fmt.Sprintf(`\(%s+\)%s?(%s+\.%s*|\.%s+)`, rNb10, rSign, rNbN, rNbN, rNbN)
|
regDec16 = regexp.MustCompile(fmt.Sprintf(`(%s)(%s)((%s)*\.(%s)+|(%s)+\.)`, regBSign, regBase16, regNb16, regNb16, regNb16))
|
||||||
rDecB = fmt.Sprintf(`%s(%s|%s|%s)`, rBSign, rDec2, rDec8, rDec16)
|
|
||||||
rDec = fmt.Sprintf(`(%s|%s|%s)`, rDec10, rDecN, rDecB)
|
regFrac = regexp.MustCompile(fmt.Sprintf(`%s(%s)?%s+/(%s)?%s+`, regBase, regSign, regNb, regSign, regNb))
|
||||||
rExponent10 = fmt.Sprintf(`(%s|%s)(%s)%s?%s+`, rInt10, rDec10, rExp10, rSign, rNb10)
|
regFrac10 = regexp.MustCompile(fmt.Sprintf(`(%s)?%s+/(%s)?%s+`, regSign, regNb10, regSign, regNb10))
|
||||||
rExponentN = fmt.Sprintf(`(%s|%s)%s%s?%s+`, rInt, rDec, rExpN, rSign, rNb10)
|
|
||||||
rAll10 = fmt.Sprintf(`(%s|%s)((%s)%s?%s+)?`, rInt10, rDec10, regExp10, rSign, rNb10)
|
regSci = regexp.MustCompile(fmt.Sprintf(`%s(%s)?(%s*\.%s+|%s+\.?)%s(%s)?(%s)+`, regBase, regSign, regNb, regNb, regNb, regExp, regSign, regNb10))
|
||||||
rAllN = fmt.Sprintf(`(%s|%s)(%s%s?%s+)?`, rInt, rDec, rExpN, rSign, rNb10)
|
regSci10Simple = regexp.MustCompile(fmt.Sprintf(`%s(%s)?(%s*\.%s+|%s+\.?)`, regSign, regNb10, regNb10, regNb10, regExp, regSign, regNb10))
|
||||||
rAll = fmt.Sprintf(`(%s|%s)`, rAll10, rAllN)
|
regSci10 = regexp.MustCompile(fmt.Sprintf(`%s(%s)?(%s*\.%s+|%s+\.?)`, regSign, regNb10, regNb10, regNb10, regExp10, regSign, regNb10))
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
regInt10 = regexp.MustCompile(fmt.Sprintf(`^%s$`, rInt10))
|
|
||||||
regIntN = regexp.MustCompile(fmt.Sprintf(`^%s$`, rIntN))
|
|
||||||
regIntB = regexp.MustCompile(fmt.Sprintf(`^%s$`, rIntB))
|
|
||||||
|
|
||||||
regDec = regexp.MustCompile(fmt.Sprintf(`^%s$`, rDec))
|
|
||||||
|
|
||||||
regExp10 = regexp.MustCompile(fmt.Sprintf(`^%s$`, rExponent10))
|
|
||||||
regExpN = regexp.MustCompile(fmt.Sprintf(`^%s$`, rExpN))
|
|
||||||
|
|
||||||
regFrac = regexp.MustCompile(fmt.Sprintf(`^%s/%s$`, rAll, rAll))
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,109 +9,160 @@ import (
|
||||||
"gitea.zaclys.com/bvaudour/gob/option"
|
"gitea.zaclys.com/bvaudour/gob/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Undefined retourne un nombre indéfini, signé :
|
func undefinedString(sign int) string {
|
||||||
// - si sign < 0, retourne -∞
|
switch sign {
|
||||||
// - si sign > 0, retourne +∞
|
case -1:
|
||||||
// - sinon, retourne NaN
|
return "-∞"
|
||||||
func Undefined[N integer | float](sign N) Number {
|
case +1:
|
||||||
return Number{
|
return "+∞"
|
||||||
base: 10,
|
default:
|
||||||
tpe: Integer,
|
return "NaN"
|
||||||
sign: signOf(sign),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nan retourne NaN.
|
func integerString(n *big.Int, base uint, sign int) string {
|
||||||
func Nan() Number { return Undefined(0) }
|
out := n.Text(int(base))
|
||||||
|
|
||||||
// Inf retourne +∞.
|
if sign < 0 {
|
||||||
func Inf() Number { return Undefined(1) }
|
out = fmt.Sprintf("-%s", out)
|
||||||
|
|
||||||
// NegInf retourne -∞.
|
|
||||||
func NegInf() Number { return Undefined(-1) }
|
|
||||||
|
|
||||||
// IntOf0 retourne un nombre entier à partir d’un entier, et éventuellement une base.
|
|
||||||
func IntOf0(i *big.Int, base ...uint) Number {
|
|
||||||
if i == nil {
|
|
||||||
return Nan()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n := Number{
|
if base != 10 {
|
||||||
number: option.Some(new(big.Rat).SetInt(i)),
|
out = fmt.Sprintf("(%d)%s", base, out)
|
||||||
sign: 1,
|
|
||||||
base: formatBase(base...),
|
|
||||||
tpe: Integer,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return n.format()
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// IntOf retourne un nombre entier à partir d’un entier, et éventuellement une base.
|
func fractionString(n, d *big.Int, base uint, sign int) string {
|
||||||
func IntOf[N integer | float](i N, base ...uint) Number {
|
out := fmt.Sprintf("%s/%s", n.Text(int(base)), d.Text(int(base)))
|
||||||
return IntOf0(new(big.Int).SetInt64(int64(i)), base...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func pow[N integer | float, M integer | float](b N, p ...M) Number {
|
if sign < 0 {
|
||||||
if len(p) > 0 {
|
out = fmt.Sprintf("-%s", out)
|
||||||
return IntOf(b).pow(int64(p[0]))
|
|
||||||
}
|
|
||||||
return IntOf(b).pow(int64(FloatingPrecision))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zero retourne le nombre 0.
|
|
||||||
func Zero(base ...uint) Number { return IntOf(0, base...) }
|
|
||||||
|
|
||||||
// One retourne le nombre 1.
|
|
||||||
func One(base ...uint) Number { return IntOf(1, base...) }
|
|
||||||
|
|
||||||
// Two retourne le nombre 2.
|
|
||||||
func Two(base ...uint) Number { return IntOf(2, base...) }
|
|
||||||
|
|
||||||
// DecOf0 retourne un nombre décimal à partir d’un rationnel.
|
|
||||||
func DecOf0(f *big.Rat, base ...uint) Number {
|
|
||||||
if f == nil {
|
|
||||||
return Nan()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n := Number{
|
if base != 10 {
|
||||||
number: option.Some(new(big.Rat).Set(f)),
|
out = fmt.Sprintf("(%d)%s", base, out)
|
||||||
sign: 1,
|
|
||||||
base: formatBase(base...),
|
|
||||||
tpe: Decimal,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return n.format()
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecOf retourne un nombre décimal à partir d’un flottant.
|
func decimalString(n Number) string {
|
||||||
func DecOf[N integer | float](f float64, base ...uint) Number {
|
base := n.Base()
|
||||||
return DecOf0(new(big.Rat).SetFloat64(float64(f)))
|
num, denom := n.num(), n.denom()
|
||||||
}
|
p := pow(base, FloatingPrecision)
|
||||||
|
num = num.mul(p)
|
||||||
|
q := num.quo(denom)
|
||||||
|
|
||||||
// FracOf0 retourne une fraction à partir d’un numérateur et d’un dénominateur entiers.
|
out := "0"
|
||||||
func FracOf0(num, denom *big.Int, base ...uint) Number {
|
if num.cmp(denom) >= 0 {
|
||||||
if num == nil || denom == nil {
|
if qn, ok := q.get(); ok {
|
||||||
return Nan()
|
out = qn.Num().Text(int(base))
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
n := Number{
|
precision := int(FloatingPrecision)
|
||||||
number: option.Some(new(big.Rat).SetFrac(num, denom)),
|
if len(out) < precision {
|
||||||
sign: 1,
|
out = fmt.Sprintf("%s%s", strings.Repeat("0", precision), out)
|
||||||
base: formatBase(base...),
|
|
||||||
tpe: Fraction,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return n.format()
|
deltaPrecision := len(out) - precision
|
||||||
|
out = fmt.Sprintf("%s.%s", out[:deltaPrecision], out[deltaPrecision:])
|
||||||
|
|
||||||
|
if !FixedPrecision {
|
||||||
|
l := len(out) - 1
|
||||||
|
for out[l] == '0' {
|
||||||
|
out, l = out[:l], l-1
|
||||||
|
}
|
||||||
|
if out == "." {
|
||||||
|
out = "0."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if n.IsNeg() {
|
||||||
|
out = fmt.Sprintf("-%s", out)
|
||||||
|
} else if q.IsZero() && !n.IsZero() {
|
||||||
|
out = fmt.Sprintf("+%s", out)
|
||||||
|
}
|
||||||
|
|
||||||
|
if base != 10 {
|
||||||
|
out = fmt.Sprintf("(%d)%s", base, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// FracOf retourne une fraction à partir d’un numérateur et d’un dénominateur entiers.
|
func scientificStsring(n Number) string {
|
||||||
func FracOf[N integer | float](num, denom N, base ...uint) Number {
|
base := n.Base()
|
||||||
return FracOf0(new(big.Int).SetInt64(int64(num)), new(big.Int).SetInt64(int64(denom)), base...)
|
var exponent int
|
||||||
|
tmp := n
|
||||||
|
if n.IsZero() {
|
||||||
|
num, denom := n.Abs().NumDenom()
|
||||||
|
nl, dl := num.Len(), denom.Len()
|
||||||
|
exponent := nl - dl
|
||||||
|
if exponent > 0 {
|
||||||
|
denom = denom.Mul(Number{
|
||||||
|
base: base,
|
||||||
|
tpe: Integer,
|
||||||
|
atom: pow(base, exponent),
|
||||||
|
})
|
||||||
|
} else if exponent < 0 {
|
||||||
|
num = num.Mul(Number{
|
||||||
|
base: base,
|
||||||
|
tpe: Integer,
|
||||||
|
atom: pow(base, -exponent),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if num.Lt(denom) {
|
||||||
|
exponent--
|
||||||
|
num.Mul(Int(base, base))
|
||||||
|
}
|
||||||
|
tmp = num.Div(denom)
|
||||||
|
}
|
||||||
|
|
||||||
|
out := decimalString(tmp)
|
||||||
|
|
||||||
|
signExponent := ""
|
||||||
|
if exponent > 0 {
|
||||||
|
signExponent = "+"
|
||||||
|
} else if exponent < 0 {
|
||||||
|
signExponent = "-"
|
||||||
|
}
|
||||||
|
|
||||||
|
if base == 10 {
|
||||||
|
return fmt.Sprintf("%sE%s%d", out, signExponent, exponent)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s×%d^%s%d", out, base, signExponent, exponent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBaseN(str string) (next string, base option.Option[uint]) {
|
// String retourne la représentation du nombre sous forme de chaîne de caractères.
|
||||||
|
func (n Number) String() string {
|
||||||
|
if nb, ok := n.get(); ok {
|
||||||
|
switch n.Type() {
|
||||||
|
case Integer:
|
||||||
|
return integerString(nb.Num(), n.Base(), n.Sign())
|
||||||
|
case Fraction:
|
||||||
|
return fractionString(nb.Num(), nb.Denom(), n.base, n.Sign())
|
||||||
|
case Scientific:
|
||||||
|
return scientificStsring(n)
|
||||||
|
default:
|
||||||
|
return decimalString(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefinedString(n.Sign())
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBase(str string) (next string, base option.Option[uint]) {
|
||||||
begin := strings.Index(str, "(")
|
begin := strings.Index(str, "(")
|
||||||
end := strings.Index(str, ")")
|
end := strings.Index(str, ")")
|
||||||
|
if begin > end || begin < 0 || end < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
next = str[end+1:]
|
next = str[end+1:]
|
||||||
if b, err := strconv.ParseUint(str[begin+1:end], 10, 64); err == nil && isBaseValid(b) {
|
if b, err := strconv.ParseUint(str[begin+1:end], 10, 64); err == nil && isBaseValid(b) {
|
||||||
|
@ -120,7 +171,7 @@ func parseBaseN(str string) (next string, base option.Option[uint]) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBaseB(str string) (next string, base uint) {
|
func parseBaseN(str string) (next string, base uint) {
|
||||||
next = str[1:]
|
next = str[1:]
|
||||||
switch str[0] {
|
switch str[0] {
|
||||||
case 'B', 'b':
|
case 'B', 'b':
|
||||||
|
@ -134,7 +185,7 @@ func parseBaseB(str string) (next string, base uint) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSignN(str string) (next string, sign int) {
|
func parseSign(str string) (next string, sign int) {
|
||||||
switch str[0] {
|
switch str[0] {
|
||||||
case '-':
|
case '-':
|
||||||
next, sign = str[1:], -1
|
next, sign = str[1:], -1
|
||||||
|
@ -147,7 +198,7 @@ func parseSignN(str string) (next string, sign int) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseSignB(str string) (next string, sign int) {
|
func parseSignN(str string) (next string, sign int) {
|
||||||
next, sign = str[1:], 1
|
next, sign = str[1:], 1
|
||||||
if str[0] == '1' {
|
if str[0] == '1' {
|
||||||
sign = -1
|
sign = -1
|
||||||
|
@ -166,40 +217,226 @@ func parseNumber(str string, base uint) (n option.Option[*big.Int]) {
|
||||||
|
|
||||||
func setInt(str string, base uint, sign int) (n option.Option[Number]) {
|
func setInt(str string, base uint, sign int) (n option.Option[Number]) {
|
||||||
if nb, ok := parseNumber(str, base).Get(); ok {
|
if nb, ok := parseNumber(str, base).Get(); ok {
|
||||||
if sign < 0 {
|
nn := Number{
|
||||||
nb.Neg(nb)
|
base: base,
|
||||||
|
tpe: Integer,
|
||||||
|
atom: entire0(nb, sign),
|
||||||
}
|
}
|
||||||
n = option.Some(IntOf0(nb, base))
|
n = option.Some(nn.format())
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseInt10(str string) (n option.Option[Number]) {
|
func parseInt(str string) (n option.Option[Number]) {
|
||||||
next, sign := parseSignN(str)
|
next, base := parseBase(str)
|
||||||
|
|
||||||
return setInt(next, 10, sign)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseIntB(str string) (n option.Option[Number]) {
|
|
||||||
next, sign := parseSignB(str)
|
|
||||||
next, base := parseBaseB(next)
|
|
||||||
|
|
||||||
return setInt(next, base, sign)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseIntN(str string) (n option.Option[Number]) {
|
|
||||||
next, base := parseBaseN(str)
|
|
||||||
if b, ok := base.Get(); ok {
|
if b, ok := base.Get(); ok {
|
||||||
next, sign := parseSignN(next)
|
next, sign := parseSign(next)
|
||||||
n = setInt(next, b, sign)
|
n = setInt(next, b, sign)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseInt10(str string) (n option.Option[Number]) {
|
||||||
|
next, sign := parseSign(str)
|
||||||
|
|
||||||
|
return setInt(next, 10, sign)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseIntN(str string) (n option.Option[Number]) {
|
||||||
|
next, sign := parseSignN(str)
|
||||||
|
next, base := parseBaseN(next)
|
||||||
|
|
||||||
|
return setInt(next, base, sign)
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFrac(str string, base uint, sign int) (n option.Option[Number]) {
|
||||||
|
i := strings.Index(str, "/")
|
||||||
|
if i < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sNum, sDenom := str[:i], str[i:]
|
||||||
|
if num, ok := parseNumber(sNum, base).Get(); ok {
|
||||||
|
if denom, ok := parseNumber(sDenom, base).Get(); ok {
|
||||||
|
nn := Number{
|
||||||
|
base: base,
|
||||||
|
tpe: Fraction,
|
||||||
|
atom: frac0(num, denom, sign),
|
||||||
|
}
|
||||||
|
n = option.Some(nn.format())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFrac(str string) (n option.Option[Number]) {
|
||||||
|
next, base := parseBase(str)
|
||||||
|
|
||||||
|
if b, ok := base.Get(); ok {
|
||||||
|
next, sign := parseSign(next)
|
||||||
|
n = setFrac(next, b, sign)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseFrac10(str string) (n option.Option[Number]) {
|
||||||
|
next, sign := parseSign(str)
|
||||||
|
|
||||||
|
return setFrac(next, 10, sign)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDot(str string) (next string, dot int) {
|
||||||
|
i := strings.Index(str, ".")
|
||||||
|
if i >= 0 {
|
||||||
|
next = str[:i] + str[:i]
|
||||||
|
dot = len(next) - i
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func setDec(str string, base uint, sign int) (n option.Option[Number]) {
|
||||||
|
next, dot := parseDot(str)
|
||||||
|
|
||||||
|
if num, ok := parseNumber(next, base).Get(); ok {
|
||||||
|
denom := pow(base, dot)
|
||||||
|
nn := Number{
|
||||||
|
base: base,
|
||||||
|
tpe: Decimal,
|
||||||
|
atom: entire0(num, sign).div(denom),
|
||||||
|
}
|
||||||
|
n = option.Some(nn.format())
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDec(str string) (n option.Option[Number]) {
|
||||||
|
next, base := parseBase(str)
|
||||||
|
|
||||||
|
if b, ok := base.Get(); ok {
|
||||||
|
next, sign := parseSign(next)
|
||||||
|
n = setDec(next, b, sign)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDec10(str string) (n option.Option[Number]) {
|
||||||
|
next, sign := parseSign(str)
|
||||||
|
|
||||||
|
return setDec(next, 10, sign)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDecN(str string) (n option.Option[Number]) {
|
||||||
|
next, sign := parseSignN(str)
|
||||||
|
next, base := parseBaseN(next)
|
||||||
|
|
||||||
|
return setDec(next, base, sign)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseExp(str string) (next string, baseExponent option.Option[int], exponent option.Option[int]) {
|
||||||
|
begin := strings.Index(str, "x")
|
||||||
|
end := strings.Index(str, "^")
|
||||||
|
if begin > end || begin < 0 || end < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sBase, sExponent := str[begin+1:end], str[end+1:]
|
||||||
|
|
||||||
|
if b, err := strconv.Atoi(sBase); err == nil && isBaseValid(b) {
|
||||||
|
if e, err := strconv.Atoi(sExponent); err == nil {
|
||||||
|
next, baseExponent, exponent = str[:begin], option.Some(b), option.Some(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseExp10(str string) (next string, exponent option.Option[int]) {
|
||||||
|
i := strings.Index(strings.ToLower(str), "e")
|
||||||
|
if i < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
sExponent := str[i+1:]
|
||||||
|
|
||||||
|
if e, err := strconv.Atoi(sExponent); err == nil {
|
||||||
|
next, exponent = str[:i], option.Some(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func setSci(str string, base uint, sign, baseExponent, exponent int) (n option.Option[Number]) {
|
||||||
|
next, dot := parseDot(str)
|
||||||
|
|
||||||
|
if num, ok := parseNumber(next, base).Get(); ok {
|
||||||
|
denom := pow(base, dot)
|
||||||
|
nn := Number{
|
||||||
|
base: base,
|
||||||
|
tpe: Scientific,
|
||||||
|
atom: entire0(num, sign).div(denom),
|
||||||
|
}
|
||||||
|
if exponent > 0 {
|
||||||
|
nn.atom = nn.atom.mul(pow(baseExponent, exponent))
|
||||||
|
} else if exponent < 0 {
|
||||||
|
nn.atom = nn.atom.div(pow(baseExponent, -exponent))
|
||||||
|
}
|
||||||
|
|
||||||
|
n = option.Some(nn.format())
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSci(str string) (n option.Option[Number]) {
|
||||||
|
next, base := parseBase(str)
|
||||||
|
|
||||||
|
if b, ok := base.Get(); ok {
|
||||||
|
next, sign := parseSign(next)
|
||||||
|
next, be, e := parseExp(next)
|
||||||
|
if baseExponent, ok := be.Get(); ok {
|
||||||
|
if exponent, ok := e.Get(); ok {
|
||||||
|
n = setSci(next, b, sign, baseExponent, exponent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSci10(str string) (n option.Option[Number]) {
|
||||||
|
next, sign := parseSign(str)
|
||||||
|
next, be, e := parseExp(next)
|
||||||
|
|
||||||
|
if baseExponent, ok := be.Get(); ok {
|
||||||
|
if exponent, ok := e.Get(); ok {
|
||||||
|
n = setSci(next, 10, sign, baseExponent, exponent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSci10Simple(str string) (n option.Option[Number]) {
|
||||||
|
next, sign := parseSign(str)
|
||||||
|
next, e := parseExp10(next)
|
||||||
|
|
||||||
|
if exponent, ok := e.Get(); ok {
|
||||||
|
n = setSci(next, 10, sign, 10, exponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Parse retourne un nombre à partir d’une chaîne de caractères.
|
// Parse retourne un nombre à partir d’une chaîne de caractères.
|
||||||
func Parse(str string) (out option.Option[Number]) {
|
func Parse(str string) option.Option[Number] {
|
||||||
switch str {
|
switch str {
|
||||||
case "+∞", "<inf>", "<+inf>":
|
case "+∞", "<inf>", "<+inf>":
|
||||||
return option.Some(Inf())
|
return option.Some(Inf())
|
||||||
|
@ -210,50 +447,33 @@ func Parse(str string) (out option.Option[Number]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
case regInt.MatchString(str):
|
||||||
|
return parseInt(str)
|
||||||
case regInt10.MatchString(str):
|
case regInt10.MatchString(str):
|
||||||
return parseInt10(str)
|
return parseInt10(str)
|
||||||
case regIntB.MatchString(str):
|
case regInt2.MatchString(str), regInt8.MatchString(str), regInt16.MatchString(str):
|
||||||
return parseIntB(str)
|
|
||||||
case regIntN.MatchString(str):
|
|
||||||
return parseIntN(str)
|
return parseIntN(str)
|
||||||
case regDec.MatchString(str):
|
|
||||||
l := len(str)
|
|
||||||
i := strings.Index(str, ".")
|
|
||||||
dot := l - 1 - i
|
|
||||||
str = fmt.Sprintf("%s%s", str[:i], str[i+1:])
|
|
||||||
if n, ok := Parse(str).Get(); ok {
|
|
||||||
out = option.Some(n.Div(pow(n.Base(), dot)).ToType(Decimal))
|
|
||||||
}
|
|
||||||
case regExp10.MatchString(str):
|
|
||||||
i := strings.Index(strings.ToLower(str), "e")
|
|
||||||
if exponent, err := strconv.Atoi(str[i+1:]); err == nil {
|
|
||||||
if n, ok := Parse(str[:i]).Get(); ok {
|
|
||||||
out = option.Some(n.Mul(pow(10, exponent)).ToType(Scientific))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case regExpN.MatchString(str):
|
|
||||||
i, j := strings.Index(str, "×"), strings.Index(str, "^")
|
|
||||||
if expBase, err := strconv.ParseUint(str[i+1:j], 10, 64); err == nil && isBaseValid(expBase) {
|
|
||||||
if exponent, err := strconv.Atoi(str[j+1:]); err == nil {
|
|
||||||
if n, ok := Parse(str[:i]).Get(); ok {
|
|
||||||
out = option.Some(n.Mul(pow(expBase, exponent)).ToType(Scientific))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case regFrac.MatchString(str):
|
case regFrac.MatchString(str):
|
||||||
i := strings.Index(str, "/")
|
return parseFrac(str)
|
||||||
num, denom := Parse(str[:i]), Parse(str[i:])
|
case regFrac10.MatchString(str):
|
||||||
if n, ok := num.Get(); ok {
|
return parseFrac10(str)
|
||||||
if d, ok := denom.Get(); ok {
|
case regDec.MatchString(str):
|
||||||
out = option.Some(n.Div(d).ToType(Fraction))
|
return parseInt(str)
|
||||||
}
|
case regDec10.MatchString(str):
|
||||||
}
|
return parseInt10(str)
|
||||||
|
case regDec2.MatchString(str), regDec8.MatchString(str), regDec16.MatchString(str):
|
||||||
|
return parseIntN(str)
|
||||||
|
case regSci.MatchString(str):
|
||||||
|
return parseSci(str)
|
||||||
|
case regSci10.MatchString(str):
|
||||||
|
return parseSci10(str)
|
||||||
|
case regSci10Simple.MatchString(str):
|
||||||
|
return parseSci10Simple(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return option.None[Number]()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseBool retourne 1 si vrai, et 0 sinon.
|
|
||||||
func ParseBool(b bool) Number {
|
func ParseBool(b bool) Number {
|
||||||
if b {
|
if b {
|
||||||
return One()
|
return One()
|
||||||
|
@ -261,5 +481,6 @@ func ParseBool(b bool) Number {
|
||||||
return Zero()
|
return Zero()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToBool retourne vrai si le nombre n’est ni NaN ni 0.
|
func ToBool(n Number) bool {
|
||||||
func ToBool(n Number) bool { return n.Sign() != 0 }
|
return !n.IsZero() && !n.IsNan()
|
||||||
|
}
|
||||||
|
|
873
number/number.go
873
number/number.go
File diff suppressed because it is too large
Load Diff
|
@ -11,7 +11,6 @@ type Op2To2Func func(Number, Number) (Number, Number)
|
||||||
type ReduceFunc func(...Number) Number
|
type ReduceFunc func(...Number) Number
|
||||||
type MapFunc func(...Number) []Number
|
type MapFunc func(...Number) []Number
|
||||||
|
|
||||||
// ToBase convertit n selon la base donnée.
|
|
||||||
func ToBase[N integer](n Number, base N) Number {
|
func ToBase[N integer](n Number, base N) Number {
|
||||||
return n.ToBase(formatBase(base))
|
return n.ToBase(formatBase(base))
|
||||||
}
|
}
|
||||||
|
@ -25,33 +24,36 @@ func toType[N integer](n Number, t NumberType, base ...N) Number {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToInteger convertit n en entier.
|
func ToInteger[N integer](n Number, base ...N) Number {
|
||||||
func ToInteger[N integer](n Number, base ...N) Number { return toType(n, Integer, base...) }
|
return toType(n, Integer, base...)
|
||||||
|
}
|
||||||
|
|
||||||
// ToDecimal convertit n en décimal.
|
func ToDecimal[N integer](n Number, base ...N) Number {
|
||||||
func ToDecimal[N integer](n Number, base ...N) Number { return toType(n, Decimal, base...) }
|
return toType(n, Decimal, base...)
|
||||||
|
}
|
||||||
|
|
||||||
// ToFraction convertit n en fraction.
|
func ToFraction[N integer](n Number, base ...N) Number {
|
||||||
func ToFraction[N integer](n Number, base ...N) Number { return toType(n, Fraction, base...) }
|
return toType(n, Fraction, base...)
|
||||||
|
}
|
||||||
|
|
||||||
// ToScientific convertit n en nombre scientifique.
|
func ToScientific[N integer](n Number, base ...N) Number {
|
||||||
func ToScientific[N integer](n Number, base ...N) Number { return toType(n, Scientific, base...) }
|
return toType(n, Scientific, base...)
|
||||||
|
}
|
||||||
|
|
||||||
// Fonctions de type f(n) → n
|
// Fonctions de type f(n) → n
|
||||||
func Neg(n Number) Number { return n.Neg() }
|
func Neg(n Number) Number { return n.Neg() }
|
||||||
func Abs(n Number) Number { return n.Abs() }
|
func Abs(n Number) Number { return n.Abs() }
|
||||||
func Num(n Number) Number { return n.Num() }
|
func Num(n Number) Number { return n.Num() }
|
||||||
func Denom(n Number) Number { return n.Denom() }
|
func Denom(n Number) Number { return n.Denom() }
|
||||||
func Inc(n Number) Number { return n.Inc() }
|
func Inc(n Number) Number { return n.Inc() }
|
||||||
func Dec(n Number) Number { return n.Dec() }
|
func Dec(n Number) Number { return n.Dec() }
|
||||||
func Inv(n Number) Number { return n.Inv() }
|
func Inv(n Number) Number { return n.Inv() }
|
||||||
func Fact(n Number) Number { return n.Fact() }
|
func Fact(n Number) Number { return n.Fact() }
|
||||||
func Len(n Number) Number { return IntOf(n.Len()) }
|
func Len(n Number) Number { return Int(n.Len()) }
|
||||||
func Sqrt(n Number) Number { return n.Sqrt() }
|
func Sqrt(n Number) Number { return n.Sqrt() }
|
||||||
func Square(n Number) Number { return n.Square() }
|
|
||||||
|
|
||||||
// Fonctions de type f(n, n) → n
|
// Fonctions de type f(n, n) → n
|
||||||
func Cmp(n1, n2 Number) Number { return IntOf(n1.Cmp(n2)) }
|
func Cmp(n1, n2 Number) Number { return Int(n1.Cmp(n2)) }
|
||||||
func Eq(n1, n2 Number) Number { return ParseBool(n1.Eq(n2)) }
|
func Eq(n1, n2 Number) Number { return ParseBool(n1.Eq(n2)) }
|
||||||
func Ne(n1, n2 Number) Number { return ParseBool(n1.Ne(n2)) }
|
func Ne(n1, n2 Number) Number { return ParseBool(n1.Ne(n2)) }
|
||||||
func Gt(n1, n2 Number) Number { return ParseBool(n1.Gt(n2)) }
|
func Gt(n1, n2 Number) Number { return ParseBool(n1.Gt(n2)) }
|
||||||
|
@ -66,7 +68,7 @@ func Quo(n1, n2 Number) Number { return n1.Quo(n2) }
|
||||||
func Rem(n1, n2 Number) Number { return n1.Rem(n2) }
|
func Rem(n1, n2 Number) Number { return n1.Rem(n2) }
|
||||||
func Lsh(n1, n2 Number) Number { return n1.Lsh(n2) }
|
func Lsh(n1, n2 Number) Number { return n1.Lsh(n2) }
|
||||||
func Rsh(n1, n2 Number) Number { return n1.Rsh(n2) }
|
func Rsh(n1, n2 Number) Number { return n1.Rsh(n2) }
|
||||||
func Bit(n1, n2 Number) Number { return IntOf(n1.Bit(n2)) }
|
func Bit(n1, n2 Number) Number { return Int(n1.Bit(n2)) }
|
||||||
func Pow(n1, n2 Number) Number { return n1.Pow(n2) }
|
func Pow(n1, n2 Number) Number { return n1.Pow(n2) }
|
||||||
func Sqrtn(n1, n2 Number) Number { return n1.Sqrtn(n2) }
|
func Sqrtn(n1, n2 Number) Number { return n1.Sqrtn(n2) }
|
||||||
|
|
||||||
|
@ -103,7 +105,6 @@ func Reduce(callback Op2Func) ReduceFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Max retourne le nombre le plus grand de la liste.
|
|
||||||
func Max(numbers ...Number) (n Number) {
|
func Max(numbers ...Number) (n Number) {
|
||||||
return Reduce(func(n1, n2 Number) Number {
|
return Reduce(func(n1, n2 Number) Number {
|
||||||
if n2.Gt(n1) {
|
if n2.Gt(n1) {
|
||||||
|
@ -113,7 +114,6 @@ func Max(numbers ...Number) (n Number) {
|
||||||
})(numbers...)
|
})(numbers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Min retourne le nombre le plus petit de la liste.
|
|
||||||
func Min(numbers ...Number) (n Number) {
|
func Min(numbers ...Number) (n Number) {
|
||||||
return Reduce(func(n1, n2 Number) Number {
|
return Reduce(func(n1, n2 Number) Number {
|
||||||
if n2.Lt(n1) {
|
if n2.Lt(n1) {
|
||||||
|
@ -123,100 +123,35 @@ func Min(numbers ...Number) (n Number) {
|
||||||
})(numbers...)
|
})(numbers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sum retourne la somme des nombres.
|
func Sum(numbers ...Number) (n Number) {
|
||||||
func Sum(numbers ...Number) (n Number) { return Reduce(Add)(numbers...) }
|
return Reduce(Add)(numbers...)
|
||||||
|
}
|
||||||
|
|
||||||
// Mean retourne la moyenne des nombres.
|
|
||||||
func Mean(numbers ...Number) (n Number) {
|
func Mean(numbers ...Number) (n Number) {
|
||||||
l := len(numbers)
|
l := len(numbers)
|
||||||
if l == 0 {
|
if l == 0 {
|
||||||
return Nan()
|
return Nan()
|
||||||
}
|
}
|
||||||
|
|
||||||
return Sum(numbers...).Div(IntOf(l))
|
return Sum(numbers...).Div(Int(l))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Median retourne la médiane des nombres.
|
|
||||||
func Median(numbers ...Number) Number {
|
|
||||||
l := len(numbers)
|
|
||||||
if l == 0 {
|
|
||||||
return Nan()
|
|
||||||
}
|
|
||||||
|
|
||||||
numbers = Sort(numbers...)
|
|
||||||
if l&1 == 0 {
|
|
||||||
i := l >> 1
|
|
||||||
return numbers[i].Add(numbers[i-1]).Div(Two())
|
|
||||||
}
|
|
||||||
|
|
||||||
return numbers[l>>1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mode retourne retourne le mode des nombres (ie. le nombre le plus fréquent).
|
|
||||||
func Mode(numbers ...Number) Number {
|
|
||||||
l := len(numbers)
|
|
||||||
if l == 0 {
|
|
||||||
return Nan()
|
|
||||||
}
|
|
||||||
|
|
||||||
m := make(map[Number]int)
|
|
||||||
loop:
|
|
||||||
for _, n := range numbers {
|
|
||||||
for k := range m {
|
|
||||||
if k.Eq(n) {
|
|
||||||
m[k]++
|
|
||||||
continue loop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m[n] = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
var n Number
|
|
||||||
for k, j := range m {
|
|
||||||
if j > i {
|
|
||||||
n, i = k, j
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// Variance retourne la variance des nombres.
|
|
||||||
func Variance(numbers ...Number) Number {
|
|
||||||
m := Mean(numbers...)
|
|
||||||
if m.IsNan() {
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
numbers = Map(func(n Number) Number {
|
|
||||||
return n.Sub(m).Square()
|
|
||||||
})(numbers...)
|
|
||||||
|
|
||||||
return Mean(numbers...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// StdDeviation retourne l’écart-type des nombres.
|
|
||||||
func StdDeviation(numbers ...Number) Number { return Variance(numbers...).Sqrt() }
|
|
||||||
|
|
||||||
// Round arrondit le n selon la précision et la base données.
|
|
||||||
func Round(n Number, precision uint64, base ...uint) Number {
|
func Round(n Number, precision uint64, base ...uint) Number {
|
||||||
if !n.IsDefined() || n.Type() == Integer {
|
if !n.IsDefined() || n.Type() == Integer {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
b := n.Base()
|
p := Number{
|
||||||
if len(base) > 0 {
|
base: n.Base(),
|
||||||
b = formatBase(base...)
|
tpe: n.Type(),
|
||||||
|
atom: pow(formatBase(base...), precision),
|
||||||
}
|
}
|
||||||
|
p.format()
|
||||||
p := pow(b, precision)
|
|
||||||
num, denom := n.Num().Mul(p), n.Denom()
|
num, denom := n.Num().Mul(p), n.Denom()
|
||||||
|
|
||||||
return num.Quo(denom).Div(p).ToType(n.Type())
|
return num.Quo(denom).Div(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reverse inverse l’ordre de la liste des nombres.
|
|
||||||
func Reverse(numbers ...Number) []Number {
|
func Reverse(numbers ...Number) []Number {
|
||||||
l := len(numbers)
|
l := len(numbers)
|
||||||
for i := 0; i < l>>1; i++ {
|
for i := 0; i < l>>1; i++ {
|
||||||
|
@ -227,7 +162,6 @@ func Reverse(numbers ...Number) []Number {
|
||||||
return numbers
|
return numbers
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort trie les nombres par ordre croissant.
|
|
||||||
func Sort(numbers ...Number) []Number {
|
func Sort(numbers ...Number) []Number {
|
||||||
sort.Slice(numbers, func(i, j int) bool {
|
sort.Slice(numbers, func(i, j int) bool {
|
||||||
return numbers[i].Lt(numbers[j])
|
return numbers[i].Lt(numbers[j])
|
||||||
|
@ -236,7 +170,6 @@ func Sort(numbers ...Number) []Number {
|
||||||
return numbers
|
return numbers
|
||||||
}
|
}
|
||||||
|
|
||||||
// SortDesc trie les nombres par ordre décroissant.
|
|
||||||
func SortDesc(numbers ...Number) []Number {
|
func SortDesc(numbers ...Number) []Number {
|
||||||
sort.Slice(numbers, func(i, j int) bool {
|
sort.Slice(numbers, func(i, j int) bool {
|
||||||
return numbers[i].Gt(numbers[j])
|
return numbers[i].Gt(numbers[j])
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
package number
|
package number
|
||||||
|
|
||||||
import (
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"gitea.zaclys.com/bvaudour/gob/option"
|
|
||||||
)
|
|
||||||
|
|
||||||
type integer interface {
|
type integer interface {
|
||||||
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
||||||
}
|
}
|
||||||
|
@ -14,8 +8,6 @@ type float interface {
|
||||||
~float32 | ~float64
|
~float32 | ~float64
|
||||||
}
|
}
|
||||||
|
|
||||||
type rat = option.Option[*big.Rat]
|
|
||||||
|
|
||||||
func signOf[N integer | float](n N) int {
|
func signOf[N integer | float](n N) int {
|
||||||
switch {
|
switch {
|
||||||
case n < 0:
|
case n < 0:
|
||||||
|
@ -27,14 +19,6 @@ func signOf[N integer | float](n N) int {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func abs[N integer | float](n N) N {
|
|
||||||
if n < 0 {
|
|
||||||
return -n
|
|
||||||
}
|
|
||||||
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func compare[N integer | float](n1, n2 N) int {
|
func compare[N integer | float](n1, n2 N) int {
|
||||||
return signOf(n1 - n2)
|
return signOf(n1 - n2)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
package option
|
package option
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Result stocke un résultat :
|
// Result stocke un résultat :
|
||||||
// - soit le résultat est valide, et une valeur est stockée,
|
// - soit le résultat est valide, et une valeur est stockée,
|
||||||
// - soit le résultat est invalide, et une erreur est stockée.
|
// - soit le résultat est invalide, et une erreur est stockée.
|
||||||
|
@ -45,11 +41,3 @@ func (r Result[T]) Err() (err error, ok bool) {
|
||||||
func (r Result[T]) IsOk() bool {
|
func (r Result[T]) IsOk() bool {
|
||||||
return r.ok
|
return r.ok
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r Result[T]) String() string {
|
|
||||||
return fmt.Sprintf(`{
|
|
||||||
value: %v,
|
|
||||||
error: %s,
|
|
||||||
ok: %v,
|
|
||||||
}`, r.v, r.err, r.ok)
|
|
||||||
}
|
|
||||||
|
|
|
@ -56,8 +56,11 @@ func (in *input) restart() {
|
||||||
n := in.readRune()
|
n := in.readRune()
|
||||||
next <- n
|
next <- n
|
||||||
|
|
||||||
r, ok := n.Ok()
|
needClose := !n.IsOk()
|
||||||
needClose := !ok || r == Lf || r == Cr || r == C_C || r == C_D
|
if !needClose {
|
||||||
|
r, ok := n.Ok()
|
||||||
|
needClose = ok && (r == Lf || r == Cr || r == C_C || r == C_D)
|
||||||
|
}
|
||||||
|
|
||||||
if needClose {
|
if needClose {
|
||||||
close(next)
|
close(next)
|
||||||
|
@ -314,21 +317,22 @@ func (in *input) nextChar() (key nkey) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var s Sequence
|
||||||
switch r {
|
switch r {
|
||||||
case Bs:
|
case Bs:
|
||||||
key = nk(keyS(A_Bs))
|
s = A_Bs
|
||||||
case 'O':
|
case 'O':
|
||||||
key = in.escO()
|
return in.escO()
|
||||||
case '[':
|
case '[':
|
||||||
key = in.escBracket()
|
return in.escBracket()
|
||||||
case 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
case 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z':
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z':
|
||||||
key = nk(keyS(Sequence(r << 16)))
|
s = Sequence(r << 16)
|
||||||
//default:
|
default:
|
||||||
// return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
in.clear()
|
in.clear()
|
||||||
|
|
||||||
return
|
return nk(keyS(s))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue