Skip to content

Commit

Permalink
Merge pull request #8 from Ton-Dynasty/math/functions
Browse files Browse the repository at this point in the history
feat: Add support for calculating square root of a fixed point float
  • Loading branch information
alan890104 authored Dec 10, 2023
2 parents 085f2eb + 1c4acc6 commit 45757ac
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 12 deletions.
30 changes: 30 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: CI

# trigger on Pull request for all branches and on push for master branch
on:
pull_request:
branches:
- '*'
push:
branches:
- master
jobs:
build:
name: Test
runs-on: ubuntu-latest
strategy:
matrix:
node: [16, 18]
steps:
- uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: 'yarn'
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Build contracts
run: yarn build
- name: Run tests
run: yarn test
7 changes: 7 additions & 0 deletions contracts/math_example.tact
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ extends native mul(self: Int, b: Int): Int;
@name(div)
extends native div(self: Int, b: Int): Int;

@name(sqrtFloat)
extends native sqrtFloat(self: Int): Int;

message Arithmetic {
floatA: Int;
floatB: Int;
Expand Down Expand Up @@ -57,6 +60,10 @@ contract MathExample with Deployable {
self.result = msg.floatA.safeDiv(msg.floatB);
return ;
}
if (msg.op == 4) {
self.result = msg.floatA.sqrtFloat();
return ;
}
}

get fun float(value: Int): Int {
Expand Down
13 changes: 13 additions & 0 deletions contracts/packages/math/float.fc
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,16 @@ int safeDiv(int floatA, int floatB) inline_ref {
return (floatA << 64) / floatB;
}

;; sqrtFloat function is used to calculate the square root of a fixed point float
;; used newton's method to approximate the square root, since the precision is 64 bit, we need to shift 32 bit back
int sqrtFloat(int x) inline_ref {
int z = (x + 1) / 2;
int y = x;
while (z < y) {
y = z;
z = (x / z + z) / 2;
}
;; y << (self.precision // 2)
;; The precision of fixed point float is 64 bit, so we need to shift 32 bit back
return y << 32;
}
60 changes: 48 additions & 12 deletions tests/math/float.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function toFloat(value: number, decimals: number = 64): bigint {
return BigInt(d.toString());
}

describe('NFTExample', () => {
describe('MathExample', () => {
let blockchain: Blockchain;
let deployer: SandboxContract<TreasuryContract>;
let mathContract: SandboxContract<MathExample>;
Expand Down Expand Up @@ -83,13 +83,11 @@ describe('NFTExample', () => {
expect(safeDivResult).toEqual(5270498306774157604n);
});

// How to test throw error?
// it('Should throw errorCode 4 if div by 0', async () => {
// const t = async () => {
// await mathContract.getDivisionByZero();
// };
// expect(t()).toThrowError(GetMethodError);
// });
it('Should throw errorCode 4 if div by 0', async () => {
await mathContract.getDivisionByZero().catch((e) => {
expect(e.exitCode).toEqual(4);
});
});

it('0.25 + 10', async () => {
const addTxs = await mathContract.send(
Expand All @@ -104,7 +102,7 @@ describe('NFTExample', () => {
op: 0n,
}
);
console.log("Add")
console.log('Add');
printTransactionFees(addTxs.transactions);
const addResult = await mathContract.getResult();
expect(Number(addResult)).toBeCloseTo(Number(toFloat(10.25)));
Expand All @@ -123,7 +121,7 @@ describe('NFTExample', () => {
op: 1n,
}
);
console.log("Sub")
console.log('Sub');
printTransactionFees(subTxs.transactions);
const subResult = await mathContract.getResult();
expect(Number(subResult)).toBeCloseTo(Number(toFloat(-9.75)));
Expand All @@ -142,7 +140,7 @@ describe('NFTExample', () => {
op: 2n,
}
);
console.log("Mul")
console.log('Mul');
printTransactionFees(mulTxs.transactions);
const mulResult = await mathContract.getResult();
expect(Number(mulResult)).toBeCloseTo(Number(toFloat(2.5)));
Expand All @@ -161,9 +159,47 @@ describe('NFTExample', () => {
op: 3n,
}
);
console.log("Div")
console.log('Div');
printTransactionFees(divTxs.transactions);
const divResult = await mathContract.getResult();
expect(Number(divResult)).toBeCloseTo(Number(toFloat(0.025)));
});

it('Sqrt 0.05', async () => {
const sqrtTxs = await mathContract.send(
deployer.getSender(),
{
value: toNano('0.05'),
},
{
$$type: 'Arithmetic',
floatA: toFloat(0.25),
floatB: 0n,
op: 4n,
}
);
console.log('Sqrt');
printTransactionFees(sqrtTxs.transactions);
const sqrtResult = await mathContract.getResult();
expect(Number(sqrtResult)).toBeCloseTo(Number(toFloat(0.5)));
});

it('Sqrt 25', async () => {
const sqrtTxs = await mathContract.send(
deployer.getSender(),
{
value: toNano('0.05'),
},
{
$$type: 'Arithmetic',
floatA: toFloat(25),
floatB: 0n,
op: 4n,
}
);
console.log('Sqrt');
printTransactionFees(sqrtTxs.transactions);
const sqrtResult = await mathContract.getResult();
expect(Number(sqrtResult)).toBeCloseTo(Number(toFloat(5)));
});
});

0 comments on commit 45757ac

Please sign in to comment.