Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: [fixedpoint] implement different mul mode #1800

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all 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
67 changes: 65 additions & 2 deletions pkg/fixedpoint/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"errors"
"fmt"
"math"
"math/big"
"os"
"strconv"
"strings"
"sync/atomic"
Expand Down Expand Up @@ -227,11 +229,11 @@ func (v Value) IsZero() bool {
}

func Mul(x, y Value) Value {
return NewFromFloat(x.Float64() * y.Float64())
return mulOp(x, y)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might make the mul func slower since there's additional function call. Can you do some bench on the changes to convince people that this works better? Also it's rare that we need to multiply an integer.

}

func (v Value) Mul(v2 Value) Value {
return NewFromFloat(v.Float64() * v2.Float64())
return mulOp(v, v2)
}

func Div(x, y Value) Value {
Expand Down Expand Up @@ -610,3 +612,64 @@ func (x Value) Clamp(min, max Value) Value {
}
return x
}

type Operator func(a, b Value) Value

// float64 mul is the current fastest implementation
var mulOp = multiplyValueWithFloat64

func init() {
fpMode := os.Getenv("FP_MODE")
switch fpMode {
case "int64":
mulOp = multiplyWithInt64

case "float64":
mulOp = multiplyValueWithFloat64

case "mathbig":
mulOp = multiplyBigInt

}

}

func multiplyBigInt(a, b Value) Value {
bigA := big.NewInt(int64(a))
bigB := big.NewInt(int64(b))
result := new(big.Int).Mul(bigA, bigB)

// 恢復精度 (除以 10^8)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please comment in English if possible

scalingFactor := big.NewInt(1e8)
result.Div(result, scalingFactor)

return Value(result.Int64())
}

func multiplyValueWithFloat64(x, y Value) Value {
return NewFromFloat(x.Float64() * y.Float64())
}

func multiplyWithInt64(a, b Value) Value {
const scaleFactor = 100000000

highA := a / 10000
lowA := a % 10000
highB := b / 10000
lowB := b % 10000

highResult := highA * highB
midResult1 := highA * lowB
midResult2 := lowA * highB
lowResult := (lowA * lowB) / 10000

// merge result
result := highResult*scaleFactor + (midResult1+midResult2)*10000 + lowResult

// add the remainder
result += scaleFactor / 2

result /= scaleFactor

return result
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

func multiplyWithInt64(a, b Value) Value {
	highA := a / 10000
	lowA := a % 10000
	highB := b / 10000
	lowB := b % 10000

	highResult := highA * highB
	midResult1 := highA * lowB
	midResult2 := lowA * highB
	lowResult := lowA * lowB

	result := (midResult1 + midResult2) + lowResult/10000
	result /= 10000
	result += highResult

	return result
}

Loading