Skip to content

Commit

Permalink
Merge pull request #1 from Ton-Dynasty:math/float
Browse files Browse the repository at this point in the history
feat: Add document for float library
  • Loading branch information
alan890104 authored Dec 10, 2023
2 parents 6a60c7b + 014670a commit dfdfa06
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 7 deletions.
2 changes: 1 addition & 1 deletion docs/jetton/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Tutorial - Jetton",
"position": 1,
"position": 2,
"link": {
"type": "generated-index"
}
Expand Down
71 changes: 71 additions & 0 deletions docs/math/Float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
sidebar_position: 1
---

# Fixed Point Float
Float library is implemented in FunC for the consideration of gas efficiency. Our implementation takes int128 as input and shifts it left by 64 bits, resulting a fixed $64$ bit space for storing decimals. Take number $7$ as example, when user transforms integer $7$ into float format, the output value will be $7*2^{64}$.

## Overview
Same as solidity, both FunC and Tact do not support float datatype. However, what if our DeFi application requires to compute some interest rate in a float format? To address this issue, early developers in Solidity adopt a fixed point floating point method, which is relatively easy and gas efficient in comparison with `IEEE 754` format. The basic idea is multiplying a number by a large constant to simulate a decimal points, effectively shifting the decimal place to the right.

For example, if we need to represent $3.14$ in smart contract, we could easily multiply it by $1000$ (shifting the decimals three place to the right), to get $3140$ as an integer. This approach simplifies computations while maintaining precision, as long as the developers carefully manage the scaling factor throughout the calculations. It is noteworthy we can substitude the constant $1000$ for any arbitrary number, thus, we can use binary shift operator to further reduce the computation complexity. In order to preserve a sufficient range to represent almost all rates in developing, we choose $2^{64}$ for the constant, which is equivalent to shift the origin number 64 bit left by the operator `<<`.

## Case Study
To explain the arithmetic (especially multiplication and division) in a simple term, we will introduce our usage step by step with elaboration. We take number $2$, $7$ and scaling factor $2^{64}$ for example in this section.

### Multiplication
Multiply $2$ by $7$ is quite easy, we directly compute $2 \times 7 = 14$. However, since we are talking about fixed point arithmetic, we need to process $2$ and $7$ into fixed point format before performing the multiplication. First, we convert these numbers into a fixed point representation by multiplying them with the scaling factor $2^{64}$. In this case, $2$ becomes $2 \times 2^{64}$ and $7$ becomes $7 \times 2^{64}$. These converted numbers are now in a format that allows for integer-based calculations while simulating floating-point precision.

Next, we perform the multiplication. In fixed point arithmetic, when we multiply two numbers, the result's scale is the square of the original scale. So, when we multiply the fixed point representations of $2$ and $7$, the calculation is equivalent to $(2 \times 2^{64}) \times (7 \times 2^{64})$. This results in a number that is scaled by $(2^{64})^2$.

However, we want our final answer to be in the same scale as our original inputs, which is $2^{64}$. To achieve this, we divide our result by the scaling factor $2^{64}$. This step readjusts the scale of the result back to our intended scale. The final computation is therefore $((2 \times 2^{64}) \times (7 \times 2^{64})) / 2^{64}$, which gives us the correctly scaled result of $2.5$ in fixed point format.

By leveraging our implementation, you can simply do the above procedure in Tact Language:

```js
import "./packages/math/float.fc";

@name(safeMul)
extends native safeMul(self: Int, b: Int): Int;

contract MathExample with Deployable {
x: Int = 2;
y: Int = 7;

get fun safeMul(): Int {
let a: Int = self.x.toFloat();
let b: Int = self.y.toFloat();
return a.safeMul(b);
}
}
```

### Division

Division in fixed point arithmetic follows a logic similar to multiplication, but with a few differences to accommodate the nature of division. Using the same numbers $2$, $7$, and scaling factor $2^{64}$ as in the multiplication example, let's break down the process of division.

First, like in multiplication, we convert our numbers into fixed point format using the scaling factor $2^{64}$. So, $2$ becomes $2 \times 2^{64}$ and $7$ becomes $7 \times 2^{64}$. These numbers are now ready for arithmetic operations in fixed point format.

When performing division in fixed point arithmetic, it's important to maintain the scale of the result consistent with the scale of the inputs. To divide $2$ by $7$ in fixed point format, we calculate $(2 \times 2^{64}) / (7 \times 2^{64})$. Here, the scaling factors in the numerator and denominator cancel each other out. This leaves us with the division of the original numbers, which is $2 / 7 = 0$.

However, this direct division would lead to a loss of precision since $floor(2 / 7) = 0$. To address this, we can multiply the numerator by an additional scaling factor before performing the division, and divide it at the end of computation. This means we calculate $((2 \times 2^{64}) \times 2^{64}) / (7 \times 2^{64}) / 2^{64}$. Now, the result of this division will align with the scale of our inputs.

In Tact Language, this division process can be implemented as follows:

```js
import "./packages/math/float.fc";

@name(safeDiv)
extends native safeDiv(self: Int, b: Int): Int;

contract MathExample with Deployable {
x: Int = 2;
y: Int = 7;

get fun safeDiv(): Int {
let a: Int = self.x.toFloat();
let b: Int = self.y.toFloat();
return a.safeDiv(b);
}
}
```
7 changes: 7 additions & 0 deletions docs/math/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"label": "Tutorial - Math",
"position": 1,
"link": {
"type": "generated-index"
}
}
2 changes: 1 addition & 1 deletion docs/nft/_category_.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"label": "Tutorial - NFT",
"position": 2,
"position": 3,
"link": {
"type": "generated-index",
"description": "10 minutes to write your own NFT auction contract"
Expand Down
14 changes: 14 additions & 0 deletions docusaurus.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

const lightCodeTheme = require("prism-react-renderer/themes/github");
const darkCodeTheme = require("prism-react-renderer/themes/dracula");
const math = require('remark-math');
const katex = require('rehype-katex');

/** @type {import('@docusaurus/types').Config} */
const config = {
Expand Down Expand Up @@ -42,6 +44,8 @@ const config = {
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
editUrl: "https://github.com/Ton-Dynasty/tondynasty-contracts/pulls",
remarkPlugins: [math],
rehypePlugins: [katex],
},
blog: {
showReadingTime: true,
Expand All @@ -56,6 +60,16 @@ const config = {
],
],

stylesheets: [
{
href: 'https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css',
type: 'text/css',
integrity:
'sha384-odtC+0UGzzFL/6PNoE8rX/SPcQDXBJ+uRepguP4QkPCm2LBxH3FA3y+fKSiJ+AmM',
crossorigin: 'anonymous',
},
],

themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@
"@fortawesome/react-fontawesome": "^0.2.0",
"@mdx-js/react": "^1.6.22",
"clsx": "^1.2.1",
"hast-util-is-element": "1.1.0",
"prism-react-renderer": "^1.3.5",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react-dom": "^17.0.2",
"rehype-katex": "5",
"remark-math": "3"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^2.4.3",
Expand All @@ -47,4 +50,4 @@
"engines": {
"node": ">=16.14"
}
}
}
64 changes: 61 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2109,6 +2109,11 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85"
integrity sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==

"@types/katex@^0.11.0":
version "0.11.1"
resolved "https://registry.yarnpkg.com/@types/katex/-/katex-0.11.1.tgz#34de04477dcf79e2ef6c8d23b41a3d81f9ebeaf5"
integrity sha512-DUlIj2nk0YnJdlWgsFuVKcX27MLW0KbKmGVoUHmFr+74FYYNUDAaj9ZqTADvsbE8rfxuVmSFc7KczYn5Y09ozg==

"@types/mdast@^3.0.0":
version "3.0.13"
resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.13.tgz#b7ba6e52d0faeb9c493e32c205f3831022be4e1b"
Expand Down Expand Up @@ -3067,7 +3072,7 @@ commander@^7.2.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==

commander@^8.3.0:
commander@^8.0.0, commander@^8.3.0:
version "8.3.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
Expand Down Expand Up @@ -4319,6 +4324,11 @@ hast-util-from-parse5@^6.0.0:
vfile-location "^3.2.0"
web-namespaces "^1.0.0"

[email protected], hast-util-is-element@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz#3b3ed5159a2707c6137b48637fbfe068e175a425"
integrity sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ==

hast-util-parse-selector@^2.0.0:
version "2.2.5"
resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a"
Expand Down Expand Up @@ -4351,6 +4361,15 @@ hast-util-to-parse5@^6.0.0:
xtend "^4.0.0"
zwitch "^1.0.0"

hast-util-to-text@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/hast-util-to-text/-/hast-util-to-text-2.0.1.tgz#04f2e065642a0edb08341976084aa217624a0f8b"
integrity sha512-8nsgCARfs6VkwH2jJU9b8LNTuR4700na+0h3PqCaEk4MAnMDeu5P0tP8mjk9LLNGxIeQRLbiDbZVw6rku+pYsQ==
dependencies:
hast-util-is-element "^1.0.0"
repeat-string "^1.0.0"
unist-util-find-after "^3.0.0"

hastscript@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640"
Expand Down Expand Up @@ -4942,6 +4961,13 @@ jsonfile@^6.0.1:
optionalDependencies:
graceful-fs "^4.1.6"

katex@^0.13.0:
version "0.13.24"
resolved "https://registry.yarnpkg.com/katex/-/katex-0.13.24.tgz#fe55455eb455698cb24b911a353d16a3c855d905"
integrity sha512-jZxYuKCma3VS5UuxOx/rFV1QyGSl3Uy/i0kTJF3HgQ5xMinCQVF8Zd4bMY/9aI9b9A2pjIBOsjSSm68ykTAr8w==
dependencies:
commander "^8.0.0"

keyv@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9"
Expand Down Expand Up @@ -6388,6 +6414,26 @@ regjsparser@^0.9.1:
dependencies:
jsesc "~0.5.0"

rehype-katex@5:
version "5.0.0"
resolved "https://registry.yarnpkg.com/rehype-katex/-/rehype-katex-5.0.0.tgz#b556f24fde918f28ba1cb642ea71c7e82f3373d7"
integrity sha512-ksSuEKCql/IiIadOHiKRMjypva9BLhuwQNascMqaoGLDVd0k2NlE2wMvgZ3rpItzRKCd6vs8s7MFbb8pcR0AEg==
dependencies:
"@types/katex" "^0.11.0"
hast-util-to-text "^2.0.0"
katex "^0.13.0"
rehype-parse "^7.0.0"
unified "^9.0.0"
unist-util-visit "^2.0.0"

rehype-parse@^7.0.0:
version "7.0.1"
resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-7.0.1.tgz#58900f6702b56767814afc2a9efa2d42b1c90c57"
integrity sha512-fOiR9a9xH+Le19i4fGzIEowAbwG7idy2Jzs4mOrFWBSJ0sNUgy0ev871dwWnbOo371SjgjG4pwzrbgSVrKxecw==
dependencies:
hast-util-from-parse5 "^6.0.0"
parse5 "^6.0.0"

relateurl@^0.2.7:
version "0.2.7"
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
Expand All @@ -6407,6 +6453,11 @@ [email protected]:
resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-2.0.0.tgz#9001c4c2ffebba55695d2dd80ffb8b82f7e6303f"
integrity sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ==

remark-math@3:
version "3.0.1"
resolved "https://registry.yarnpkg.com/remark-math/-/remark-math-3.0.1.tgz#85a02a15b15cad34b89a27244d4887b3a95185bb"
integrity sha512-epT77R/HK0x7NqrWHdSV75uNLwn8g9qTyMqCRCDujL0vj/6T6+yhdrR7mjELWtkse+Fw02kijAaBuVcHBor1+Q==

[email protected]:
version "1.6.22"
resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.22.tgz#06a8dab07dcfdd57f3373af7f86bd0e992108bbd"
Expand Down Expand Up @@ -6461,7 +6512,7 @@ renderkid@^3.0.0:
lodash "^4.17.21"
strip-ansi "^6.0.1"

repeat-string@^1.5.4:
repeat-string@^1.0.0, repeat-string@^1.5.4:
version "1.6.1"
resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637"
integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==
Expand Down Expand Up @@ -7241,7 +7292,7 @@ [email protected]:
trough "^1.0.0"
vfile "^4.0.0"

unified@^9.2.2:
unified@^9.0.0, unified@^9.2.2:
version "9.2.2"
resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975"
integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ==
Expand All @@ -7265,6 +7316,13 @@ [email protected], unist-builder@^2.0.0:
resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-2.0.3.tgz#77648711b5d86af0942f334397a33c5e91516436"
integrity sha512-f98yt5pnlMWlzP539tPc4grGMsFaQQlP/vM396b00jngsiINumNmsY8rkXjfoi1c6QaM8nQ3vaGDuoKWbe/1Uw==

unist-util-find-after@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/unist-util-find-after/-/unist-util-find-after-3.0.0.tgz#5c65fcebf64d4f8f496db46fa8fd0fbf354b43e6"
integrity sha512-ojlBqfsBftYXExNu3+hHLfJQ/X1jYY/9vdm4yZWjIbf0VuWF6CRufci1ZyoD/wV2TYMKxXUoNuoqwy+CkgzAiQ==
dependencies:
unist-util-is "^4.0.0"

unist-util-generated@^1.0.0:
version "1.1.6"
resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.6.tgz#5ab51f689e2992a472beb1b35f2ce7ff2f324d4b"
Expand Down

0 comments on commit dfdfa06

Please sign in to comment.