Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 120 additions & 10 deletions query/aggregator.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,30 @@ func applyAdd(a, b, c *types.Val) error {
vBase := getValType(a)
switch vBase {
case INT:
c.Value = a.Value.(int64) + b.Value.(int64)
aVal, bVal := a.Value.(int64), b.Value.(int64)

if aVal > 0 && bVal > math.MaxInt64-aVal {
return ErrorIntOverflow
}

if aVal < 0 && bVal < math.MinInt64-aVal {
return ErrorIntOverflow
}

c.Value = aVal + bVal

case FLOAT:
c.Value = a.Value.(float64) + b.Value.(float64)
aVal, bVal := a.Value.(float64), b.Value.(float64)

if aVal > 0 && bVal > math.MaxFloat64-aVal {
return ErrorFloatOverflow
}

if aVal < 0 && bVal < math.MaxFloat64-aVal {
return ErrorFloatOverflow
}

c.Value = aVal + bVal

case DEFAULT:
return errors.Errorf("Wrong type %v encountered for func +", a.Tid)
Expand All @@ -131,10 +151,30 @@ func applySub(a, b, c *types.Val) error {
vBase := getValType(a)
switch vBase {
case INT:
c.Value = a.Value.(int64) - b.Value.(int64)
aVal, bVal := a.Value.(int64), b.Value.(int64)

if bVal < 0 && aVal > math.MaxInt64+bVal {
return ErrorIntOverflow
}

if bVal > 0 && aVal < math.MinInt64+bVal {
return ErrorIntOverflow
}

c.Value = aVal - bVal

case FLOAT:
c.Value = a.Value.(float64) - b.Value.(float64)
aVal, bVal := a.Value.(float64), b.Value.(float64)

if bVal < 0 && aVal > math.MaxFloat64+bVal {
return ErrorFloatOverflow
}

if bVal > 0 && aVal < -math.MaxFloat64+bVal {
return ErrorFloatOverflow
}

c.Value = aVal - bVal

case DEFAULT:
return errors.Errorf("Wrong type %v encountered for func -", a.Tid)
Expand All @@ -146,10 +186,26 @@ func applyMul(a, b, c *types.Val) error {
vBase := getValType(a)
switch vBase {
case INT:
c.Value = a.Value.(int64) * b.Value.(int64)
aVal, bVal := a.Value.(int64), b.Value.(int64)
c.Value = aVal * bVal

if aVal == 0 || bVal == 0 || aVal == 1 || bVal == 1 {
Comment thread
rohanprasad marked this conversation as resolved.
Outdated
return nil
} else if aVal == math.MinInt64 || bVal == math.MinInt64 || c.Value.(int64)/bVal != aVal {
Comment thread
rohanprasad marked this conversation as resolved.
Outdated
// TODO: Check if +- INF should be returned
return ErrorIntOverflow
}

case FLOAT:
c.Value = a.Value.(float64) * b.Value.(float64)
aVal, bVal := a.Value.(float64), b.Value.(float64)
c.Value = aVal * bVal

if aVal == 0 || bVal == 0 || aVal == 1 || bVal == 1 {
return nil
} else if math.Abs(c.Value.(float64)/bVal)-aVal > 0.001 {
// TODO: Check if +- INF should be returned
return ErrorFloatOverflow
}

case DEFAULT:
return errors.Errorf("Wrong type %v encountered for func *", a.Tid)
Expand All @@ -162,13 +218,13 @@ func applyDiv(a, b, c *types.Val) error {
switch vBase {
case INT:
if b.Value.(int64) == 0 {
return errors.Errorf("Division by zero")
return ErrorDivisionByZero
}
c.Value = a.Value.(int64) / b.Value.(int64)

case FLOAT:
if b.Value.(float64) == 0 {
return errors.Errorf("Division by zero")
return ErrorDivisionByZero
}
c.Value = a.Value.(float64) / b.Value.(float64)

Expand All @@ -183,13 +239,13 @@ func applyMod(a, b, c *types.Val) error {
switch vBase {
case INT:
if b.Value.(int64) == 0 {
return errors.Errorf("Module by zero")
return ErrorModuloByZero
}
c.Value = a.Value.(int64) % b.Value.(int64)

case FLOAT:
if b.Value.(float64) == 0 {
return errors.Errorf("Module by zero")
return ErrorModuloByZero
}
c.Value = math.Mod(a.Value.(float64), b.Value.(float64))

Expand All @@ -204,11 +260,27 @@ func applyPow(a, b, c *types.Val) error {
switch vBase {
case INT:
c.Value = math.Pow(float64(a.Value.(int64)), float64(b.Value.(int64)))
// TODO: Check if +- INF should be returned
if math.IsInf(c.Value.(float64), 0) {
return ErrorFloatOverflow
}

c.Tid = types.FloatID

case FLOAT:
// TODO: Check if +- INF should be returned
// Fractional power of -ve numbers should not be returned.
if a.Value.(float64) < 0 &&
math.Ceil(b.Value.(float64))-b.Value.(float64) > 0 {
return ErrorFractionalPower
}
c.Value = math.Pow(a.Value.(float64), b.Value.(float64))

// TODO: Check if +- INF should be returned
if math.IsInf(c.Value.(float64), 0) {
return ErrorFloatOverflow
}

case DEFAULT:
return errors.Errorf("Wrong type %v encountered for func ^", a.Tid)
}
Expand All @@ -219,10 +291,18 @@ func applyLog(a, b, c *types.Val) error {
vBase := getValType(a)
switch vBase {
case INT:
// TODO: Check if +- INF should be returned, log(0?, 0?)
if a.Value.(int64) < 0 || b.Value.(int64) < 0 {
Comment thread
rohanprasad marked this conversation as resolved.
return ErrorNegativeLog
}
c.Value = math.Log(float64(a.Value.(int64))) / math.Log(float64(b.Value.(int64)))
c.Tid = types.FloatID

case FLOAT:
// TODO: Check if +- INF should be returned, log(0?, 0?)
if a.Value.(float64) < 0 || b.Value.(float64) < 0 {
return ErrorNegativeLog
}
c.Value = math.Log(a.Value.(float64)) / math.Log(b.Value.(float64))

case DEFAULT:
Expand Down Expand Up @@ -261,10 +341,16 @@ func applyLn(a, res *types.Val) error {
vBase := getValType(a)
switch vBase {
case INT:
if a.Value.(int64) < 0 {
return ErrorNegativeLog
}
res.Value = math.Log(float64(a.Value.(int64)))
res.Tid = types.FloatID

case FLOAT:
if a.Value.(float64) < 0 {
return ErrorNegativeLog
}
res.Value = math.Log(a.Value.(float64))

case DEFAULT:
Expand All @@ -274,13 +360,27 @@ func applyLn(a, res *types.Val) error {
}

func applyExp(a, res *types.Val) error {
// For IEEE double
// if x > 7.09782712893383973096e+02 then exp(x) overflow
// if x < -7.45133219101941108420e+02 then exp(x) underflow
const (
Overflow = 7.09782712893383973096e+02
Underflow = -7.45133219101941108420e+02
)

vBase := getValType(a)
switch vBase {
case INT:
if float64(a.Value.(int64)) > Overflow || float64(a.Value.(int64)) < Underflow {
return ErrorFloatOverflow
}
res.Value = math.Exp(float64(a.Value.(int64)))
res.Tid = types.FloatID

case FLOAT:
if a.Value.(float64) > Overflow || a.Value.(float64) < Underflow {
return ErrorFloatOverflow
}
res.Value = math.Exp(a.Value.(float64))

case DEFAULT:
Expand All @@ -293,6 +393,10 @@ func applyNeg(a, res *types.Val) error {
vBase := getValType(a)
switch vBase {
case INT:
// -ve of math.MinInt64 is evaluated as itself (due to overflow)
if a.Value.(int64) == math.MinInt64 {
return ErrorIntOverflow
}
res.Value = -a.Value.(int64)

case FLOAT:
Expand All @@ -308,10 +412,16 @@ func applySqrt(a, res *types.Val) error {
vBase := getValType(a)
switch vBase {
case INT:
if a.Value.(int64) < 0 {
return ErrorNegativeRoot
}
res.Value = math.Sqrt(float64(a.Value.(int64)))
res.Tid = types.FloatID

case FLOAT:
if a.Value.(float64) < 0 {
return ErrorNegativeRoot
}
res.Value = math.Sqrt(a.Value.(float64))

case DEFAULT:
Expand Down
10 changes: 10 additions & 0 deletions query/math.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ type mathTree struct {
Child []*mathTree
}

var (
ErrorIntOverflow = errors.New("Integer overflow")
ErrorFloatOverflow = errors.New("Float overflow")
Comment thread
rohanprasad marked this conversation as resolved.
Outdated
ErrorDivisionByZero = errors.New("Division by zero")
ErrorModuloByZero = errors.New("Modulo by zero")
Comment thread
rohanprasad marked this conversation as resolved.
Outdated
ErrorFractionalPower = errors.New("Fractional power of negative number")
ErrorNegativeLog = errors.New("Log of negative number")
ErrorNegativeRoot = errors.New("Root of negative number")
Comment thread
rohanprasad marked this conversation as resolved.
)

// processBinary handles the binary operands like
// +, -, *, /, %, max, min, logbase
func processBinary(mNode *mathTree) error {
Expand Down
Loading