func ArithmeticMinus(a, b Number) (Number, error) {
	if xi, ok := a.LosslessInt(); ok {
		if yi, ok := b.LosslessInt(); ok {
			r := new(big.Int).Sub(xi, yi)
			return NewBigInt(r), nil
		}
	}
	if xr, ok := a.LosslessRat(); ok {
		if yr, ok := b.LosslessRat(); ok {
			r := new(big.Rat).Sub(xr, yr)
			return NewBigRat(r), nil
		}
	}
	r := a.Float64() - b.Float64()
	return NewFloat64(r), nil
}
Subtract two Golog numbers returning the result as a new Golog number
package term
import "fmt"
import "math/big"
import . "github.com/mndrix/golog/util"
type Number interface {
	Term
	Float64() float64
	LosslessInt() (*big.Int, bool)
	LosslessRat() (*big.Rat, bool)
}
func IsInteger(t Term) bool {
	return t.Type() == IntegerType
}
func IsFloat(t Term) bool {
	return t.Type() == FloatType
}
func IsRational(t Term) bool {
	switch t.(type) {
	case *Rational:
		return true
	default:
		return false
	}
}
func IsNumber(t Term) bool {
	return IsInteger(t) || IsFloat(t) || IsRational(t)
}
func ArithmeticEval(t0 Term) (Number, error) {
	Debugf("arith eval: %s\n", t0)
	if IsNumber(t0) {
		return t0.(Number), nil
	}
	var t Callable
	if IsCallable(t0) {
		t = t0.(Callable)
	} else {
		msg := fmt.Sprintf("Unexpected arithmetic term: %s", t0)
		panic(msg)
	}
	if t.Arity() == 2 {
		args := t.Arguments()
		a, b, err := ArithmeticEval2(args[0], args[1])
		if err != nil {
			return nil, err
		}
		switch t.Name() {
		case "*":  
			return ArithmeticMultiply(a, b)
		case "+":  
			return ArithmeticAdd(a, b)
		case "-":  
			return ArithmeticMinus(a, b)
		case "/":  
			return ArithmeticDivide(a, b)
		}
	}
	msg := fmt.Errorf("Not an expression: %s", t)
	return nil, msg
}
func ArithmeticEval2(first, second Term) (Number, Number, error) {
	a, err := ArithmeticEval(first)
	if err != nil {
		return nil, nil, err
	}
	b, err := ArithmeticEval(second)
	if err != nil {
		return nil, nil, err
	}
	return a, b, nil
}
func ArithmeticAdd(a, b Number) (Number, error) {
	if xi, ok := a.LosslessInt(); ok {
		if yi, ok := b.LosslessInt(); ok {
			r := new(big.Int).Add(xi, yi)
			return NewBigInt(r), nil
		}
	}
	if xr, ok := a.LosslessRat(); ok {
		if yr, ok := b.LosslessRat(); ok {
			r := new(big.Rat).Add(xr, yr)
			return NewBigRat(r), nil
		}
	}
	r := a.Float64() + b.Float64()
	return NewFloat64(r), nil
}
func ArithmeticDivide(a, b Number) (Number, error) {
	if xi, ok := a.LosslessInt(); ok {
		if yi, ok := b.LosslessInt(); ok {
			r := new(big.Rat).SetFrac(xi, yi)
			return NewBigRat(r), nil
		}
	}
	if xr, ok := a.LosslessRat(); ok {
		if yr, ok := b.LosslessRat(); ok {
			r := new(big.Rat).Quo(xr, yr)
			return NewBigRat(r), nil
		}
	}
	r := a.Float64() / b.Float64()
	return NewFloat64(r), nil
}