Merge PR #5428: Add mod, exponentiation for uint

This commit is contained in:
Kevin Davis 2019-12-19 16:46:43 -05:00 committed by Alexander Bezobchuk
parent cf4645213d
commit 876beef634
3 changed files with 67 additions and 3 deletions

View File

@ -76,7 +76,7 @@ if the provided arguments are invalid.
`StdTx.Signatures` to get back the array of StdSignatures `[]StdSignature`.
* (modules) [\#5299](https://github.com/cosmos/cosmos-sdk/pull/5299) `HandleDoubleSign` along with params `MaxEvidenceAge`
and `DoubleSignJailEndTime` have moved from the `x/slashing` module to the `x/evidence` module.
* (keys) [\#4941](https://github.com/cosmos/cosmos-sdk/issues/4941) Initializing a new keybase through `NewKeyringFromHomeFlag`, `NewKeyringFromDir`, `NewKeyBaseFromHomeFlag`, `NewKeyBaseFromDir`, or `NewInMemory` functions now accept optional parameters of type `KeybaseOption`. These optional parameters are also added on the keys subcommands functions, which are now public, and allows these options to be set on the commands or ignored to default to previous behavior.
* (keys) [\#4941](https://github.com/cosmos/cosmos-sdk/issues/4941) Initializing a new keybase through `NewKeyringFromHomeFlag`, `NewKeyringFromDir`, `NewKeyBaseFromHomeFlag`, `NewKeyBaseFromDir`, or `NewInMemory` functions now accept optional parameters of type `KeybaseOption`. These optional parameters are also added on the keys subcommands functions, which are now public, and allows these options to be set on the commands or ignored to default to previous behavior.
* The option introduced in this PR is `WithKeygenFunc` which allows a custom bytes to key implementation to be defined when keys are created.
* (simapp) [\#5419](https://github.com/cosmos/cosmos-sdk/pull/5419) simapp/helpers.GenTx() now accepts a gas argument.
@ -213,11 +213,12 @@ to detail this new feature and how state transitions occur.
* (docs/spec) All module specs moved into their respective module dir in x/ (i.e. docs/spec/staking -->> x/staking/spec)
* (docs/) [\#5379](https://github.com/cosmos/cosmos-sdk/pull/5379) Major documentation refactor, including:
* (docs/intro/) Add and improve introduction material for newcomers.
* (docs/basics/) Add documentation about basic concepts of the cosmos sdk such as the anatomy of an SDK application, the transaction lifecycle or accounts.
* (docs/core/) Add documentation about core conepts of the cosmos sdk such as `baseapp`, `server`, `store`s, `context` and more.
* (docs/basics/) Add documentation about basic concepts of the cosmos sdk such as the anatomy of an SDK application, the transaction lifecycle or accounts.
* (docs/core/) Add documentation about core conepts of the cosmos sdk such as `baseapp`, `server`, `store`s, `context` and more.
* (docs/building-modules/) Add reference documentation on concepts relevant for module developers (`keeper`, `handler`, `messages`, `queries`,...).
* (docs/interfaces/) Add documentation on building interfaces for the Cosmos SDK.
* Redesigned user interface that features new dynamically generated sidebar, build-time code embedding from GitHub, new homepage as well as many other improvements.
* (types) [\#5428](https://github.com/cosmos/cosmos-sdk/pull/5428) Add `Mod` (modulo) method and `RelativePow` (exponentation) function for `Uint`.
### Bug Fixes

View File

@ -99,6 +99,14 @@ func (u Uint) MulUint64(u2 uint64) (res Uint) { return u.Mul(NewUint(u2)) }
// Quo divides Uint with Uint
func (u Uint) Quo(u2 Uint) (res Uint) { return NewUintFromBigInt(div(u.i, u2.i)) }
// Mod returns remainder after dividing with Uint
func (u Uint) Mod(u2 Uint) Uint {
if u2.IsZero() {
panic("division-by-zero")
}
return Uint{mod(u.i, u2.i)}
}
// Quo divides Uint with uint64
func (u Uint) QuoUint64(u2 uint64) Uint { return u.Quo(NewUint(u2)) }
@ -172,3 +180,39 @@ func checkNewUint(i *big.Int) (Uint, error) {
}
return Uint{i}, nil
}
// RelativePow raises x to the power of n, where x (and the result, z) are scaled by factor b
// for example, RelativePow(210, 2, 100) = 441 (2.1^2 = 4.41)
func RelativePow(x Uint, n Uint, b Uint) (z Uint) {
if x.IsZero() {
if n.IsZero() {
z = b // 0^0 = 1
return
}
z = ZeroUint() // otherwise 0^a = 0
return
}
z = x
if n.Mod(NewUint(2)).Equal(ZeroUint()) {
z = b
}
halfOfB := b.Quo(NewUint(2))
n = n.Quo(NewUint(2))
for n.GT(ZeroUint()) {
xSquared := x.Mul(x)
xSquaredRounded := xSquared.Add(halfOfB)
x = xSquaredRounded.Quo(b)
if n.Mod(NewUint(2)).Equal(OneUint()) {
zx := z.Mul(x)
zxRounded := zx.Add(halfOfB)
z = zxRounded.Quo(b)
}
n = n.Quo(NewUint(2))
}
return z
}

View File

@ -256,3 +256,22 @@ func TestParseUint(t *testing.T) {
func randuint() Uint {
return NewUint(rand.Uint64())
}
func TestRelativePow(t *testing.T) {
tests := []struct {
args []Uint
want Uint
}{
{[]Uint{ZeroUint(), ZeroUint(), OneUint()}, OneUint()},
{[]Uint{ZeroUint(), ZeroUint(), NewUint(10)}, NewUint(10)},
{[]Uint{ZeroUint(), OneUint(), NewUint(10)}, ZeroUint()},
{[]Uint{NewUint(10), NewUint(2), OneUint()}, NewUint(100)},
{[]Uint{NewUint(210), NewUint(2), NewUint(100)}, NewUint(441)},
{[]Uint{NewUint(2100), NewUint(2), NewUint(1000)}, NewUint(4410)},
{[]Uint{NewUint(1000000001547125958), NewUint(600), NewUint(1000000000000000000)}, NewUint(1000000928276004850)},
}
for i, tc := range tests {
res := RelativePow(tc.args[0], tc.args[1], tc.args[2])
require.Equal(t, tc.want, res, "unexpected result for test case %d, input: %v, got: %v", i, tc.args, res)
}
}