mirror of
https://codeberg.org/scip/tablizer.git
synced 2025-12-19 05:21:03 +01:00
added
This commit is contained in:
246
vendor/github.com/glycerine/zygomys/zygo/numerictower.go
generated
vendored
Normal file
246
vendor/github.com/glycerine/zygomys/zygo/numerictower.go
generated
vendored
Normal file
@@ -0,0 +1,246 @@
|
||||
package zygo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
)
|
||||
|
||||
type IntegerOp int
|
||||
|
||||
const (
|
||||
ShiftLeft IntegerOp = iota
|
||||
ShiftRightArith
|
||||
ShiftRightLog
|
||||
Modulo
|
||||
BitAnd
|
||||
BitOr
|
||||
BitXor
|
||||
)
|
||||
|
||||
var WrongType error = errors.New("operands have invalid type")
|
||||
|
||||
func IntegerDo(op IntegerOp, a, b Sexp) (Sexp, error) {
|
||||
var ia *SexpInt
|
||||
var ib *SexpInt
|
||||
|
||||
switch i := a.(type) {
|
||||
case *SexpInt:
|
||||
ia = i
|
||||
case *SexpUint64:
|
||||
return UintegerDo(op, i, b)
|
||||
case *SexpChar:
|
||||
ia = &SexpInt{Val: int64(i.Val)}
|
||||
default:
|
||||
return SexpNull, WrongType
|
||||
}
|
||||
|
||||
switch i := b.(type) {
|
||||
case *SexpInt:
|
||||
ib = i
|
||||
case *SexpUint64:
|
||||
return UintegerDo(op, &SexpUint64{Val: uint64(ia.Val)}, b)
|
||||
case *SexpChar:
|
||||
ib = &SexpInt{Val: int64(i.Val)}
|
||||
default:
|
||||
return SexpNull, WrongType
|
||||
}
|
||||
|
||||
switch op {
|
||||
case ShiftLeft:
|
||||
return &SexpInt{Val: ia.Val << uint(ib.Val)}, nil
|
||||
case ShiftRightArith:
|
||||
return &SexpInt{Val: ia.Val >> uint(ib.Val)}, nil
|
||||
case ShiftRightLog:
|
||||
return &SexpInt{Val: int64(uint(ia.Val) >> uint(ib.Val))}, nil
|
||||
case Modulo:
|
||||
return &SexpInt{Val: ia.Val % ib.Val}, nil
|
||||
case BitAnd:
|
||||
return &SexpInt{Val: ia.Val & ib.Val}, nil
|
||||
case BitOr:
|
||||
return &SexpInt{Val: ia.Val | ib.Val}, nil
|
||||
case BitXor:
|
||||
return &SexpInt{Val: ia.Val ^ ib.Val}, nil
|
||||
}
|
||||
return SexpNull, errors.New("unrecognized shift operation")
|
||||
}
|
||||
|
||||
func UintegerDo(op IntegerOp, ia *SexpUint64, b Sexp) (Sexp, error) {
|
||||
var ib *SexpUint64
|
||||
|
||||
switch i := b.(type) {
|
||||
case *SexpUint64:
|
||||
ib = i
|
||||
case *SexpInt:
|
||||
ib = &SexpUint64{Val: uint64(i.Val)}
|
||||
case *SexpChar:
|
||||
ib = &SexpUint64{Val: uint64(i.Val)}
|
||||
default:
|
||||
return SexpNull, WrongType
|
||||
}
|
||||
|
||||
switch op {
|
||||
case ShiftLeft:
|
||||
return &SexpUint64{Val: ia.Val << ib.Val}, nil
|
||||
case ShiftRightArith:
|
||||
return &SexpUint64{Val: ia.Val >> ib.Val}, nil
|
||||
case ShiftRightLog:
|
||||
return &SexpUint64{Val: ia.Val >> ib.Val}, nil
|
||||
case Modulo:
|
||||
return &SexpUint64{Val: ia.Val % ib.Val}, nil
|
||||
case BitAnd:
|
||||
return &SexpUint64{Val: ia.Val & ib.Val}, nil
|
||||
case BitOr:
|
||||
return &SexpUint64{Val: ia.Val | ib.Val}, nil
|
||||
case BitXor:
|
||||
return &SexpUint64{Val: ia.Val ^ ib.Val}, nil
|
||||
}
|
||||
return SexpNull, errors.New("unrecognized shift operation")
|
||||
}
|
||||
|
||||
type NumericOp int
|
||||
|
||||
const (
|
||||
Add NumericOp = iota
|
||||
Sub
|
||||
Mult
|
||||
Div
|
||||
Pow
|
||||
)
|
||||
|
||||
func NumericFloatDo(op NumericOp, a, b *SexpFloat) Sexp {
|
||||
switch op {
|
||||
case Add:
|
||||
return &SexpFloat{Val: a.Val + b.Val}
|
||||
case Sub:
|
||||
return &SexpFloat{Val: a.Val - b.Val}
|
||||
case Mult:
|
||||
return &SexpFloat{Val: a.Val * b.Val}
|
||||
case Div:
|
||||
return &SexpFloat{Val: a.Val / b.Val}
|
||||
case Pow:
|
||||
return &SexpFloat{Val: math.Pow(float64(a.Val), float64(b.Val))}
|
||||
}
|
||||
return SexpNull
|
||||
}
|
||||
|
||||
func NumericIntDo(op NumericOp, a, b *SexpInt) Sexp {
|
||||
switch op {
|
||||
case Add:
|
||||
return &SexpInt{Val: a.Val + b.Val}
|
||||
case Sub:
|
||||
return &SexpInt{Val: a.Val - b.Val}
|
||||
case Mult:
|
||||
return &SexpInt{Val: a.Val * b.Val}
|
||||
case Div:
|
||||
if a.Val%b.Val == 0 {
|
||||
return &SexpInt{Val: a.Val / b.Val}
|
||||
} else {
|
||||
return &SexpFloat{Val: float64(a.Val) / float64(b.Val)}
|
||||
}
|
||||
case Pow:
|
||||
return &SexpInt{Val: int64(math.Pow(float64(a.Val), float64(b.Val)))}
|
||||
}
|
||||
return SexpNull
|
||||
}
|
||||
|
||||
func NumericUint64Do(op NumericOp, a, b *SexpUint64) Sexp {
|
||||
switch op {
|
||||
case Add:
|
||||
return &SexpUint64{Val: a.Val + b.Val}
|
||||
case Sub:
|
||||
return &SexpUint64{Val: a.Val - b.Val}
|
||||
case Mult:
|
||||
return &SexpUint64{Val: a.Val * b.Val}
|
||||
case Div:
|
||||
if a.Val%b.Val == 0 {
|
||||
return &SexpUint64{Val: a.Val / b.Val}
|
||||
} else {
|
||||
return &SexpFloat{Val: float64(a.Val) / float64(b.Val)}
|
||||
}
|
||||
case Pow:
|
||||
return &SexpUint64{Val: uint64(math.Pow(float64(a.Val), float64(b.Val)))}
|
||||
}
|
||||
return SexpNull
|
||||
}
|
||||
|
||||
func NumericMatchFloat(op NumericOp, a *SexpFloat, b Sexp) (Sexp, error) {
|
||||
var fb *SexpFloat
|
||||
switch tb := b.(type) {
|
||||
case *SexpFloat:
|
||||
fb = tb
|
||||
case *SexpInt:
|
||||
fb = &SexpFloat{Val: float64(tb.Val)}
|
||||
case *SexpUint64:
|
||||
fb = &SexpFloat{Val: float64(tb.Val)}
|
||||
case *SexpChar:
|
||||
fb = &SexpFloat{Val: float64(tb.Val)}
|
||||
default:
|
||||
return SexpNull, WrongType
|
||||
}
|
||||
return NumericFloatDo(op, a, fb), nil
|
||||
}
|
||||
|
||||
func NumericMatchInt(op NumericOp, a *SexpInt, b Sexp) (Sexp, error) {
|
||||
switch tb := b.(type) {
|
||||
case *SexpFloat:
|
||||
return NumericFloatDo(op, &SexpFloat{Val: float64(a.Val)}, tb), nil
|
||||
case *SexpInt:
|
||||
return NumericIntDo(op, a, tb), nil
|
||||
case *SexpUint64:
|
||||
return NumericUint64Do(op, &SexpUint64{Val: uint64(a.Val)}, tb), nil
|
||||
case *SexpChar:
|
||||
return NumericIntDo(op, a, &SexpInt{Val: int64(tb.Val)}), nil
|
||||
}
|
||||
return SexpNull, WrongType
|
||||
}
|
||||
|
||||
func NumericMatchUint64(op NumericOp, a *SexpUint64, b Sexp) (Sexp, error) {
|
||||
switch tb := b.(type) {
|
||||
case *SexpFloat:
|
||||
return NumericFloatDo(op, &SexpFloat{Val: float64(a.Val)}, tb), nil
|
||||
case *SexpInt:
|
||||
return NumericUint64Do(op, a, &SexpUint64{Val: uint64(tb.Val)}), nil
|
||||
case *SexpUint64:
|
||||
return NumericUint64Do(op, a, tb), nil
|
||||
case *SexpChar:
|
||||
return NumericUint64Do(op, a, &SexpUint64{Val: uint64(tb.Val)}), nil
|
||||
}
|
||||
return SexpNull, WrongType
|
||||
}
|
||||
|
||||
func NumericMatchChar(op NumericOp, a *SexpChar, b Sexp) (Sexp, error) {
|
||||
var res Sexp
|
||||
switch tb := b.(type) {
|
||||
case *SexpFloat:
|
||||
res = NumericFloatDo(op, &SexpFloat{Val: float64(a.Val)}, tb)
|
||||
case *SexpInt:
|
||||
res = NumericIntDo(op, &SexpInt{Val: int64(a.Val)}, tb)
|
||||
case *SexpUint64:
|
||||
return NumericUint64Do(op, &SexpUint64{Val: uint64(a.Val)}, tb), nil
|
||||
case *SexpChar:
|
||||
res = NumericIntDo(op, &SexpInt{Val: int64(a.Val)}, &SexpInt{Val: int64(tb.Val)})
|
||||
default:
|
||||
return SexpNull, WrongType
|
||||
}
|
||||
switch tres := res.(type) {
|
||||
case *SexpFloat:
|
||||
return tres, nil
|
||||
case *SexpInt:
|
||||
return &SexpChar{Val: rune(tres.Val)}, nil
|
||||
}
|
||||
return SexpNull, errors.New("unexpected result")
|
||||
}
|
||||
|
||||
func NumericDo(op NumericOp, a, b Sexp) (Sexp, error) {
|
||||
switch ta := a.(type) {
|
||||
case *SexpFloat:
|
||||
return NumericMatchFloat(op, ta, b)
|
||||
case *SexpInt:
|
||||
return NumericMatchInt(op, ta, b)
|
||||
case *SexpUint64:
|
||||
return NumericMatchUint64(op, ta, b)
|
||||
case *SexpChar:
|
||||
return NumericMatchChar(op, ta, b)
|
||||
}
|
||||
return SexpNull, WrongType
|
||||
}
|
||||
Reference in New Issue
Block a user