Skip to content

Commit

Permalink
Merge PR #5428: Add mod, exponentiation for uint
Browse files Browse the repository at this point in the history
  • Loading branch information
karzak authored and alexanderbez committed Dec 19, 2019
1 parent cf46452 commit 876beef
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 3 deletions.
7 changes: 4 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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
Expand Down
44 changes: 44 additions & 0 deletions types/uint.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)) }

Expand Down Expand Up @@ -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
}
19 changes: 19 additions & 0 deletions types/uint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

0 comments on commit 876beef

Please sign in to comment.