Skip to content

Commit

Permalink
add sqrt function
Browse files Browse the repository at this point in the history
  • Loading branch information
moodysalem committed Mar 29, 2021
1 parent c33cc04 commit 5a741a3
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 1 deletion.
3 changes: 2 additions & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sortedInsert from './sortedInsert'
import validateAndParseAddress from './validateAndParseAddress'
import sqrt from './sqrt'

export { sortedInsert, validateAndParseAddress }
export { sortedInsert, validateAndParseAddress, sqrt }
24 changes: 24 additions & 0 deletions src/utils/sqrt.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import JSBI from 'jsbi'
import { MaxUint256 } from '../constants'
import sqrt from './sqrt'

describe('#sqrt', () => {
it('correct for 0-1000', () => {
for (let i = 0; i < 1000; i++) {
expect(sqrt(JSBI.BigInt(i))).toEqual(JSBI.BigInt(Math.floor(Math.sqrt(i))))
}
})

it('correct for all even powers of 2', async () => {
for (let i = 0; i < 1000; i++) {
const root = JSBI.exponentiate(JSBI.BigInt(2), JSBI.BigInt(i))
const rootSquared = JSBI.multiply(root, root)

expect(sqrt(rootSquared)).toEqual(root)
}
})

it('correct for MaxUint256', () => {
expect(sqrt(MaxUint256)).toEqual(JSBI.BigInt('340282366920938463463374607431768211455'))
})
})
31 changes: 31 additions & 0 deletions src/utils/sqrt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import JSBI from 'jsbi'
import invariant from 'tiny-invariant'

export const MAX_SAFE_INTEGER = JSBI.BigInt(Number.MAX_SAFE_INTEGER)

const ZERO = JSBI.BigInt(0)
const ONE = JSBI.BigInt(1)
const TWO = JSBI.BigInt(2)

/**
* Computes floor(sqrt(value))
* @param value the value for which to compute the square root, rounded down
*/
export default function sqrt(value: JSBI): JSBI {
invariant(JSBI.greaterThanOrEqual(value, ZERO), 'NEGATIVE')

// rely on built in sqrt if possible
if (JSBI.lessThan(value, MAX_SAFE_INTEGER)) {
return JSBI.BigInt(Math.floor(Math.sqrt(JSBI.toNumber(value))))
}

let z: JSBI
let x: JSBI
z = value
x = JSBI.add(JSBI.divide(value, TWO), ONE)
while (JSBI.lessThan(x, z)) {
z = x
x = JSBI.divide(JSBI.add(JSBI.divide(value, x), x), TWO)
}
return z
}

0 comments on commit 5a741a3

Please sign in to comment.