Skip to content

Commit

Permalink
Merge pull request #167 from ichiban/integer_power
Browse files Browse the repository at this point in the history
add evaluable functor: integer power
  • Loading branch information
ichiban authored Mar 19, 2022
2 parents c7d6a93 + ce3603f commit 5c26462
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
19 changes: 19 additions & 0 deletions engine/number.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ var DefaultEvaluableFunctors = EvaluableFunctors{
`div`: IntFloorDiv,
`max`: Max,
`min`: Min,
`^`: IntegerPower,
},
}

Expand Down Expand Up @@ -901,6 +902,24 @@ func Min(x, y Number) (Number, error) {
}
}

// IntegerPower returns x raised to the power of y.
func IntegerPower(x, y Number) (Number, error) {
if x, ok := x.(Integer); ok {
if y, ok := y.(Integer); ok {
if x != 1 && y < -1 {
return nil, TypeErrorFloat(x)
}

r, err := Power(x, y)
if err != nil {
return nil, err
}
return truncateFtoI(r.(Float))
}
}
return Power(x, y)
}

// Comparison

func eqF(x, y Float) bool {
Expand Down
72 changes: 72 additions & 0 deletions engine/number_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1532,6 +1532,78 @@ func TestMin(t *testing.T) {
})
}

func TestIntegerPower(t *testing.T) {
t.Run("integer", func(t *testing.T) {
t.Run("integer", func(t *testing.T) {
r, err := IntegerPower(Integer(1), Integer(1))
assert.NoError(t, err)
assert.Equal(t, Integer(1), r)

t.Run("x is not equal to 1 and y is less than -1", func(t *testing.T) {
_, err := IntegerPower(Integer(2), Integer(-2))
assert.Equal(t, TypeErrorFloat(Integer(2)), err)
})
})

t.Run("float", func(t *testing.T) {
r, err := IntegerPower(Integer(1), Float(1))
assert.NoError(t, err)
assert.Equal(t, Float(1), r)
})

t.Run("not a number", func(t *testing.T) {
_, err := IntegerPower(Integer(1), mockNumber{})
assert.Equal(t, ErrUndefined, err)
})
})

t.Run("float", func(t *testing.T) {
t.Run("integer", func(t *testing.T) {
r, err := IntegerPower(Float(1), Integer(1))
assert.NoError(t, err)
assert.Equal(t, Float(1), r)
})

t.Run("float", func(t *testing.T) {
r, err := IntegerPower(Float(1), Float(1))
assert.NoError(t, err)
assert.Equal(t, Float(1), r)
})

t.Run("not a number", func(t *testing.T) {
_, err := IntegerPower(Float(1), mockNumber{})
assert.Equal(t, ErrUndefined, err)
})
})

t.Run("not a number", func(t *testing.T) {
_, err := IntegerPower(mockNumber{}, Float(1))
assert.Equal(t, ErrUndefined, err)
})

t.Run("overflow", func(t *testing.T) {
_, err := IntegerPower(Float(math.MaxFloat64), Float(2))
assert.Equal(t, ErrFloatOverflow, err)
})

t.Run("underflow", func(t *testing.T) {
_, err := IntegerPower(Float(math.SmallestNonzeroFloat64), Float(2))
assert.Equal(t, ErrUnderflow, err)
})

t.Run("undefined", func(t *testing.T) {
t.Run("vx is negative and vy is not an integer", func(t *testing.T) {
_, err := IntegerPower(Integer(-1), Float(1.1))
assert.Equal(t, ErrUndefined, err)
})

t.Run("vx is zero and vy is negative", func(t *testing.T) {
_, err := IntegerPower(Integer(0), Integer(-1))
assert.Equal(t, ErrUndefined, err)
})
})
}

type mockNumber struct {
mock.Mock
}
Expand Down

0 comments on commit 5c26462

Please sign in to comment.