ginger/core/math.go

730 lines
12 KiB
Go
Raw Normal View History

package core
import (
"fmt"
"github.com/mediocregopher/ginger/seq"
"github.com/mediocregopher/ginger/types"
)
type mathReduceFn func(types.Elem, types.Elem) types.Elem
func mathReduce(fn mathReduceFn, zero types.Elem, s seq.Seq) types.Elem {
reduceFn := func(acc, el types.Elem) (types.Elem, bool) {
return fn(acc, el), false
}
return seq.Reduce(reduceFn, zero, s)
}
func plusInt(a, b types.Elem) types.Elem {
return types.GoType{ Int(a) + Int(b) }
}
func plusInt8(a, b types.Elem) types.Elem {
return types.GoType{ Int8(a) + Int8(b) }
}
func plusInt16(a, b types.Elem) types.Elem {
return types.GoType{ Int16(a) + Int16(b) }
}
func plusInt32(a, b types.Elem) types.Elem {
return types.GoType{ Int32(a) + Int32(b) }
}
func plusInt64(a, b types.Elem) types.Elem {
return types.GoType{ Int64(a) + Int64(b) }
}
func plusUint(a, b types.Elem) types.Elem {
return types.GoType{ Uint(a) + Uint(b) }
}
func plusUint8(a, b types.Elem) types.Elem {
return types.GoType{ Uint8(a) + Uint8(b) }
}
func plusUint16(a, b types.Elem) types.Elem {
return types.GoType{ Uint16(a) + Uint16(b) }
}
func plusUint32(a, b types.Elem) types.Elem {
return types.GoType{ Uint32(a) + Uint32(b) }
}
func plusUint64(a, b types.Elem) types.Elem {
return types.GoType{ Uint64(a) + Uint64(b) }
}
func plusFloat32(a, b types.Elem) types.Elem {
return types.GoType{ Float32(a) + Float32(b) }
}
func plusFloat64(a, b types.Elem) types.Elem {
return types.GoType{ Float64(a) + Float64(b) }
}
func plusComplex64(a, b types.Elem) types.Elem {
return types.GoType{ Complex64(a) + Complex64(b) }
}
func plusComplex128(a, b types.Elem) types.Elem {
return types.GoType{ Complex128(a) + Complex128(b) }
}
func plusString(a, b types.Elem) types.Elem {
return types.GoType{ String(a) + String(b) }
}
func Plus(s seq.Seq) types.Elem {
var first, zero types.Elem
if seq.Empty(s) {
return types.GoType{ 0 }
}
first, _, _ = s.FirstRest()
var fn mathReduceFn
switch first.(types.GoType).V.(type) {
case int:
fn = plusInt
zero = types.GoType{ int(0) }
case int8:
fn = plusInt8
zero = types.GoType{ int8(0) }
case int16:
fn = plusInt16
zero = types.GoType{ int16(0) }
case int32:
fn = plusInt32
zero = types.GoType{ int32(0) }
case int64:
fn = plusInt64
zero = types.GoType{ int64(0) }
case uint:
fn = plusUint
zero = types.GoType{ uint(0) }
case uint8:
fn = plusUint8
zero = types.GoType{ uint8(0) }
case uint16:
fn = plusUint16
zero = types.GoType{ uint16(0) }
case uint32:
fn = plusUint32
zero = types.GoType{ uint32(0) }
case uint64:
fn = plusUint64
zero = types.GoType{ uint64(0) }
case float32:
fn = plusFloat32
zero = types.GoType{ float32(0) }
case float64:
fn = plusFloat64
zero = types.GoType{ float64(0) }
case complex64:
fn = plusComplex64
zero = types.GoType{ complex64(0) }
case complex128:
fn = plusComplex128
zero = types.GoType{ complex128(0) }
case string:
fn = plusString
zero = types.GoType{string("")}
default:
panic(fmt.Sprintf("$#v cannot have Plus called on it", first))
}
return mathReduce(fn, zero, s)
}
func minusInt(a, b types.Elem) types.Elem {
return types.GoType{ Int(a) - Int(b) }
}
func minusInt8(a, b types.Elem) types.Elem {
return types.GoType{ Int8(a) - Int8(b) }
}
func minusInt16(a, b types.Elem) types.Elem {
return types.GoType{ Int16(a) - Int16(b) }
}
func minusInt32(a, b types.Elem) types.Elem {
return types.GoType{ Int32(a) - Int32(b) }
}
func minusInt64(a, b types.Elem) types.Elem {
return types.GoType{ Int64(a) - Int64(b) }
}
func minusUint(a, b types.Elem) types.Elem {
return types.GoType{ Uint(a) - Uint(b) }
}
func minusUint8(a, b types.Elem) types.Elem {
return types.GoType{ Uint8(a) - Uint8(b) }
}
func minusUint16(a, b types.Elem) types.Elem {
return types.GoType{ Uint16(a) - Uint16(b) }
}
func minusUint32(a, b types.Elem) types.Elem {
return types.GoType{ Uint32(a) - Uint32(b) }
}
func minusUint64(a, b types.Elem) types.Elem {
return types.GoType{ Uint64(a) - Uint64(b) }
}
func minusFloat32(a, b types.Elem) types.Elem {
return types.GoType{ Float32(a) - Float32(b) }
}
func minusFloat64(a, b types.Elem) types.Elem {
return types.GoType{ Float64(a) - Float64(b) }
}
func minusComplex64(a, b types.Elem) types.Elem {
return types.GoType{ Complex64(a) - Complex64(b) }
}
func minusComplex128(a, b types.Elem) types.Elem {
return types.GoType{ Complex128(a) - Complex128(b) }
}
func Minus(s seq.Seq) types.Elem {
var first, zero types.Elem
if seq.Empty(s) {
panic("Minus cannot be called with no arguments")
}
zero, s, _ = s.FirstRest()
first = zero
var fn mathReduceFn
switch first.(types.GoType).V.(type) {
case int:
fn = minusInt
case int8:
fn = minusInt8
case int16:
fn = minusInt16
case int32:
fn = minusInt32
case int64:
fn = minusInt64
case uint:
fn = minusUint
case uint8:
fn = minusUint8
case uint16:
fn = minusUint16
case uint32:
fn = minusUint32
case uint64:
fn = minusUint64
case float32:
fn = minusFloat32
case float64:
fn = minusFloat64
case complex64:
fn = minusComplex64
case complex128:
fn = minusComplex128
default:
panic(fmt.Sprintf("$#v cannot have Minus called on it", first))
}
return mathReduce(fn, zero, s)
}
func multInt(a, b types.Elem) types.Elem {
return types.GoType{ Int(a) * Int(b) }
}
func multInt8(a, b types.Elem) types.Elem {
return types.GoType{ Int8(a) * Int8(b) }
}
func multInt16(a, b types.Elem) types.Elem {
return types.GoType{ Int16(a) * Int16(b) }
}
func multInt32(a, b types.Elem) types.Elem {
return types.GoType{ Int32(a) * Int32(b) }
}
func multInt64(a, b types.Elem) types.Elem {
return types.GoType{ Int64(a) * Int64(b) }
}
func multUint(a, b types.Elem) types.Elem {
return types.GoType{ Uint(a) * Uint(b) }
}
func multUint8(a, b types.Elem) types.Elem {
return types.GoType{ Uint8(a) * Uint8(b) }
}
func multUint16(a, b types.Elem) types.Elem {
return types.GoType{ Uint16(a) * Uint16(b) }
}
func multUint32(a, b types.Elem) types.Elem {
return types.GoType{ Uint32(a) * Uint32(b) }
}
func multUint64(a, b types.Elem) types.Elem {
return types.GoType{ Uint64(a) * Uint64(b) }
}
func multFloat32(a, b types.Elem) types.Elem {
return types.GoType{ Float32(a) * Float32(b) }
}
func multFloat64(a, b types.Elem) types.Elem {
return types.GoType{ Float64(a) * Float64(b) }
}
func multComplex64(a, b types.Elem) types.Elem {
return types.GoType{ Complex64(a) * Complex64(b) }
}
func multComplex128(a, b types.Elem) types.Elem {
return types.GoType{ Complex128(a) * Complex128(b) }
}
func Mult(s seq.Seq) types.Elem {
var first, zero types.Elem
if seq.Empty(s) {
return types.GoType{ 1 }
}
first, _, _ = s.FirstRest()
var fn mathReduceFn
switch first.(types.GoType).V.(type) {
case int:
fn = multInt
zero = types.GoType{ int(1) }
case int8:
fn = multInt8
zero = types.GoType{ int8(1) }
case int16:
fn = multInt16
zero = types.GoType{ int16(1) }
case int32:
fn = multInt32
zero = types.GoType{ int32(1) }
case int64:
fn = multInt64
zero = types.GoType{ int64(1) }
case uint:
fn = multUint
zero = types.GoType{ uint(1) }
case uint8:
fn = multUint8
zero = types.GoType{ uint8(1) }
case uint16:
fn = multUint16
zero = types.GoType{ uint16(1) }
case uint32:
fn = multUint32
zero = types.GoType{ uint32(1) }
case uint64:
fn = multUint64
zero = types.GoType{ uint64(1) }
case float32:
fn = multFloat32
zero = types.GoType{ float32(1) }
case float64:
fn = multFloat64
zero = types.GoType{ float64(1) }
case complex64:
fn = multComplex64
zero = types.GoType{ complex64(1) }
case complex128:
fn = multComplex128
zero = types.GoType{ complex128(1) }
default:
panic(fmt.Sprintf("$#v cannot have Mult called on it", first))
}
return mathReduce(fn, zero, s)
}
func divInt(a, b types.Elem) types.Elem {
return types.GoType{ Int(a) / Int(b) }
}
func divInt8(a, b types.Elem) types.Elem {
return types.GoType{ Int8(a) / Int8(b) }
}
func divInt16(a, b types.Elem) types.Elem {
return types.GoType{ Int16(a) / Int16(b) }
}
func divInt32(a, b types.Elem) types.Elem {
return types.GoType{ Int32(a) / Int32(b) }
}
func divInt64(a, b types.Elem) types.Elem {
return types.GoType{ Int64(a) / Int64(b) }
}
func divUint(a, b types.Elem) types.Elem {
return types.GoType{ Uint(a) / Uint(b) }
}
func divUint8(a, b types.Elem) types.Elem {
return types.GoType{ Uint8(a) / Uint8(b) }
}
func divUint16(a, b types.Elem) types.Elem {
return types.GoType{ Uint16(a) / Uint16(b) }
}
func divUint32(a, b types.Elem) types.Elem {
return types.GoType{ Uint32(a) / Uint32(b) }
}
func divUint64(a, b types.Elem) types.Elem {
return types.GoType{ Uint64(a) / Uint64(b) }
}
func divFloat32(a, b types.Elem) types.Elem {
return types.GoType{ Float32(a) / Float32(b) }
}
func divFloat64(a, b types.Elem) types.Elem {
return types.GoType{ Float64(a) / Float64(b) }
}
func divComplex64(a, b types.Elem) types.Elem {
return types.GoType{ Complex64(a) / Complex64(b) }
}
func divComplex128(a, b types.Elem) types.Elem {
return types.GoType{ Complex128(a) / Complex128(b) }
}
func Div(s seq.Seq) types.Elem {
var first, zero types.Elem
if seq.Empty(s) {
panic("Div cannot be called with no arguments")
}
zero, s, _ = s.FirstRest()
first = zero
var fn mathReduceFn
switch first.(types.GoType).V.(type) {
case int:
fn = divInt
case int8:
fn = divInt8
case int16:
fn = divInt16
case int32:
fn = divInt32
case int64:
fn = divInt64
case uint:
fn = divUint
case uint8:
fn = divUint8
case uint16:
fn = divUint16
case uint32:
fn = divUint32
case uint64:
fn = divUint64
case float32:
fn = divFloat32
case float64:
fn = divFloat64
case complex64:
fn = divComplex64
case complex128:
fn = divComplex128
default:
panic(fmt.Sprintf("$#v cannot have Div called on it", first))
}
return mathReduce(fn, zero, s)
}
func modInt(a, b types.Elem) types.Elem {
return types.GoType{ Int(a) % Int(b) }
}
func modInt8(a, b types.Elem) types.Elem {
return types.GoType{ Int8(a) % Int8(b) }
}
func modInt16(a, b types.Elem) types.Elem {
return types.GoType{ Int16(a) % Int16(b) }
}
func modInt32(a, b types.Elem) types.Elem {
return types.GoType{ Int32(a) % Int32(b) }
}
func modInt64(a, b types.Elem) types.Elem {
return types.GoType{ Int64(a) % Int64(b) }
}
func modUint(a, b types.Elem) types.Elem {
return types.GoType{ Uint(a) % Uint(b) }
}
func modUint8(a, b types.Elem) types.Elem {
return types.GoType{ Uint8(a) % Uint8(b) }
}
func modUint16(a, b types.Elem) types.Elem {
return types.GoType{ Uint16(a) % Uint16(b) }
}
func modUint32(a, b types.Elem) types.Elem {
return types.GoType{ Uint32(a) % Uint32(b) }
}
func modUint64(a, b types.Elem) types.Elem {
return types.GoType{ Uint64(a) % Uint64(b) }
}
func Mod(s seq.Seq) types.Elem {
var first, zero types.Elem
if seq.Empty(s) {
panic("Mod cannot be called with no arguments")
}
zero, s, _ = s.FirstRest()
first = zero
var fn mathReduceFn
switch first.(types.GoType).V.(type) {
case int:
fn = modInt
case int8:
fn = modInt8
case int16:
fn = modInt16
case int32:
fn = modInt32
case int64:
fn = modInt64
case uint:
fn = modUint
case uint8:
fn = modUint8
case uint16:
fn = modUint16
case uint32:
fn = modUint32
case uint64:
fn = modUint64
default:
panic(fmt.Sprintf("$#v cannot have Mod called on it", first))
}
return mathReduce(fn, zero, s)
}