{"id":19097236,"url":"https://github.com/lycantropos/rithm","last_synced_at":"2025-07-28T15:09:17.915Z","repository":{"id":45728271,"uuid":"385830292","full_name":"lycantropos/rithm","owner":"lycantropos","description":"Arbitrary precision arithmetic","archived":false,"fork":false,"pushed_at":"2024-11-19T04:35:43.000Z","size":1325,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-10T00:48:45.783Z","etag":null,"topics":["big-int","big-integer","fraction"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lycantropos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-07-14T06:00:05.000Z","updated_at":"2024-11-19T04:35:43.000Z","dependencies_parsed_at":"2023-10-16T18:48:31.583Z","dependency_job_id":"2fe4ab4a-f7c5-4aae-bb13-ef37b7ef183f","html_url":"https://github.com/lycantropos/rithm","commit_stats":{"total_commits":1400,"total_committers":1,"mean_commits":1400.0,"dds":0.0,"last_synced_commit":"778982162c7337333ac33c3622efa8e7912b566d"},"previous_names":[],"tags_count":43,"template":false,"template_full_name":null,"purl":"pkg:github/lycantropos/rithm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lycantropos%2Frithm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lycantropos%2Frithm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lycantropos%2Frithm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lycantropos%2Frithm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lycantropos","download_url":"https://codeload.github.com/lycantropos/rithm/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lycantropos%2Frithm/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267535065,"owners_count":24103230,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-28T02:00:09.689Z","response_time":68,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["big-int","big-integer","fraction"],"created_at":"2024-11-09T03:39:32.176Z","updated_at":"2025-07-28T15:09:17.866Z","avatar_url":"https://github.com/lycantropos.png","language":"Rust","readme":"rithm\n=====\n\n[![](https://github.com/lycantropos/rithm/workflows/CI/badge.svg)](https://github.com/lycantropos/rithm/actions/workflows/ci.yml \"Github Actions\")\n[![](https://codecov.io/gh/lycantropos/rithm/branch/master/graph/badge.svg)](https://codecov.io/gh/lycantropos/rithm \"Codecov\")\n[![](https://img.shields.io/github/license/lycantropos/rithm.svg)](https://github.com/lycantropos/rithm/blob/master/LICENSE \"License\")\n[![](https://badge.fury.io/py/rithm.svg)](https://badge.fury.io/py/rithm \"PyPI\")\n[![](https://img.shields.io/crates/v/rithm.svg)](https://crates.io/crates/rithm \"crates.io\")\n\nIn what follows `python` is an alias for `python3.9` or `pypy3.9`\nor any later version (`python3.10`, `pypy3.10` and so on).\n\nInstallation\n------------\n\nInstall the latest `pip` \u0026 `setuptools` packages versions\n\n```bash\npython -m pip install --upgrade pip setuptools\n```\n\n### User\n\nDownload and install the latest stable version from `PyPI` repository\n\n```bash\npython -m pip install --upgrade rithm\n```\n\n### Developer\n\nDownload the latest version from `GitHub` repository\n\n```bash\ngit clone https://github.com/lycantropos/rithm.git\ncd rithm\n```\n\nInstall dependencies\n\n```bash\npython -m pip install -r requirements.txt\n```\n\nInstall\n\n```bash\npython setup.py install\n```\n\nUsage\n-----\n\n### Python\n\n#### Arbitrary precision integer\n\nWith setup\n\n```python\n\u003e\u003e\u003e from rithm.integer import Int\n\n```\n\nwe can:\n\n- construct\n  ```python\n  \u003e\u003e\u003e Int()\n  Int(0)\n  \u003e\u003e\u003e Int(9)\n  Int(9)\n  \u003e\u003e\u003e Int('9')\n  Int(9)\n  \u003e\u003e\u003e Int('0b1001', 2)\n  Int(9)\n  \u003e\u003e\u003e Int('0o11', 8)\n  Int(9)\n  \u003e\u003e\u003e Int('0x9', 16)\n  Int(9)\n  \u003e\u003e\u003e Int('1001', 2)\n  Int(9)\n  \u003e\u003e\u003e Int('0o11', 8)\n  Int(9)\n  \u003e\u003e\u003e Int('9', 16)\n  Int(9)\n  \u003e\u003e\u003e Int(9.99)\n  Int(9)\n\n  ```\n- compare\n  ```python\n  \u003e\u003e\u003e Int(9) == Int(9)\n  True\n  \u003e\u003e\u003e Int(9) \u003e= Int(9)\n  True\n  \u003e\u003e\u003e Int(9) \u003e Int(8)\n  True\n  \u003e\u003e\u003e Int(9) \u003c= Int(9)\n  True\n  \u003e\u003e\u003e Int(9) \u003c Int(10)\n  True\n\n  ```\n- calculate\n  ```python\n  \u003e\u003e\u003e abs(Int(-9))\n  Int(9)\n  \u003e\u003e\u003e Int(4) + Int(5)\n  Int(9)\n  \u003e\u003e\u003e Int(9) \u0026 Int(11)\n  Int(9)\n  \u003e\u003e\u003e Int(19) // Int(2)\n  Int(9)\n  \u003e\u003e\u003e ~Int(-10)\n  Int(9)\n  \u003e\u003e\u003e Int(19) % Int(10)\n  Int(9)\n  \u003e\u003e\u003e Int(3) * Int(3)\n  Int(9)\n  \u003e\u003e\u003e -Int(-9)\n  Int(9)\n  \u003e\u003e\u003e Int(1) | Int(8)\n  Int(9)\n  \u003e\u003e\u003e Int(3) ** Int(2)\n  Int(9)\n  \u003e\u003e\u003e Int(5) \u003c\u003c Int(1)\n  Int(10)\n  \u003e\u003e\u003e Int(5) \u003e\u003e Int(1)\n  Int(2)\n  \u003e\u003e\u003e Int(25) - Int(16)\n  Int(9)\n  \u003e\u003e\u003e Int(18) / Int(2)\n  Fraction(Int(9), Int(1))\n  \u003e\u003e\u003e Int(2) ^ Int(11)\n  Int(9)\n\n  ```\n\n#### Exact fraction\n\nWith setup\n\n```python\n\u003e\u003e\u003e from rithm.fraction import Fraction\n\n```\n\nwe can:\n\n- construct\n  ```python\n  \u003e\u003e\u003e Fraction()\n  Fraction(Int(0), Int(1))\n  \u003e\u003e\u003e Fraction(1)\n  Fraction(Int(1), Int(1))\n  \u003e\u003e\u003e Fraction(1, 2)\n  Fraction(Int(1), Int(2))\n  \u003e\u003e\u003e Fraction(50, 100)\n  Fraction(Int(1), Int(2))\n  \u003e\u003e\u003e Fraction(0.5)\n  Fraction(Int(1), Int(2))\n\n  ```\n- compare\n  ```python\n  \u003e\u003e\u003e Fraction(1, 2) == Fraction(1, 2)\n  True\n  \u003e\u003e\u003e Fraction(1, 2) \u003e= Fraction(1, 2)\n  True\n  \u003e\u003e\u003e Fraction(1, 2) \u003e Fraction(1, 3)\n  True\n  \u003e\u003e\u003e Fraction(1, 2) \u003c Fraction(2, 3)\n  True\n  \u003e\u003e\u003e Fraction(1, 2) != Fraction(1, 3)\n  True\n\n  ```\n- calculate\n  ```python\n  \u003e\u003e\u003e abs(Fraction(-1, 2))\n  Fraction(Int(1), Int(2))\n  \u003e\u003e\u003e Fraction(1, 3) + Fraction(1, 6)\n  Fraction(Int(1), Int(2))\n  \u003e\u003e\u003e Fraction(3, 2) // Fraction(1)\n  Int(1)\n  \u003e\u003e\u003e Fraction(3, 2) % Fraction(1)\n  Fraction(Int(1), Int(2))\n  \u003e\u003e\u003e Fraction(1, 3) * Fraction(3, 2)\n  Fraction(Int(1), Int(2))\n  \u003e\u003e\u003e -Fraction(-1, 2)\n  Fraction(Int(1), Int(2))\n  \u003e\u003e\u003e Fraction(1, 2) ** 2\n  Fraction(Int(1), Int(4))\n  \u003e\u003e\u003e Fraction(3, 2) - Fraction(1)\n  Fraction(Int(1), Int(2))\n  \u003e\u003e\u003e Fraction(1, 3) / Fraction(2, 3)\n  Fraction(Int(1), Int(2))\n\n  ```\n\n### Rust\n\n#### Arbitrary precision integer\n\n```rust\n/// With setup\nuse std::convert::TryFrom;\nuse traiter::numbers::{\n    Abs, DivEuclid, FromStrRadix, Pow, RemEuclid, Zero\n};\nuse rithm::big_int;\n\n#[cfg(target_arch = \"x86\")]\ntype Digit = u16;\n#[cfg(not(target_arch = \"x86\"))]\ntype Digit = u32;\nconst DIGIT_BITNESS: usize = (Digit::BITS - 1) as usize;\nconst _: () = assert!(big_int::is_valid_digit_bitness::\u003cDigit, DIGIT_BITNESS\u003e());\ntype BigInt = big_int::BigInt\u003cDigit, DIGIT_BITNESS\u003e;\n/// we can:\n/// - construct\nassert_eq!(BigInt::zero(), 0);\nassert_eq!(BigInt::from(9), 9);\nassert_eq!(BigInt::try_from(\"9\").unwrap(), 9);\nassert_eq!(BigInt::try_from(\"0b1001\").unwrap(), 9);\nassert_eq!(BigInt::try_from(\"0o11\").unwrap(), 9);\nassert_eq!(BigInt::try_from(\"0x9\").unwrap(), 9);\nassert_eq!(BigInt::from_str_radix(\"1001\", 2).unwrap(), 9);\nassert_eq!(BigInt::from_str_radix(\"11\", 8).unwrap(), 9);\nassert_eq!(BigInt::from_str_radix(\"9\", 16).unwrap(), 9);\nassert_eq!(BigInt::try_from(9.99).unwrap(), 9);\n/// - compare\nassert!(BigInt::from(9) == BigInt::from(9));\nassert!(BigInt::from(9) \u003e= BigInt::from(9));\nassert!(BigInt::from(9) \u003e BigInt::from(8));\nassert!(BigInt::from(9) \u003c= BigInt::from(9));\nassert!(BigInt::from(9) \u003c BigInt::from(10));\n/// - calculate\nassert_eq!(BigInt::from(-9).abs(), 9);\nassert_eq!(BigInt::from(4) + BigInt::from(5), 9);\nassert_eq!(BigInt::from(9) \u0026 BigInt::from(11), 9);\nassert_eq!(BigInt::from(1) | BigInt::from(8), 9);\nassert_eq!(BigInt::from(2) ^ BigInt::from(11), 9);\nassert_eq!(BigInt::from(19) / BigInt::from(2), 9);\nassert_eq!(BigInt::from(19).div_euclid(BigInt::from(2)), 9);\nassert_eq!(BigInt::from(3) * BigInt::from(3), 9);\nassert_eq!(-BigInt::from(-9), 9);\nassert_eq!(!BigInt::from(-10), 9);\nassert_eq!(BigInt::from(3).pow(BigInt::from(2)), 9);\nassert_eq!(BigInt::from(19) % BigInt::from(10), 9);\nassert_eq!(BigInt::from(19).rem_euclid(BigInt::from(10)), 9);\nassert_eq!(BigInt::from(5) \u003c\u003c 1, 10);\nassert_eq!(BigInt::from(5) \u003e\u003e 1, 2);\nassert_eq!(BigInt::from(25) - BigInt::from(16), 9);\n```\n\n#### Exact fraction\n\n```rust\n/// With setup\nuse std::convert::TryFrom;\nuse traiter::numbers::{Abs, DivEuclid, One, Pow, RemEuclid, Zero};\nuse rithm::fraction;\n\ntype Fraction = fraction::Fraction\u003ci8\u003e;\n/// we can:\n/// - construct\nassert_eq!(Fraction::zero(), 0);\nassert_eq!(Fraction::one(), 1);\nassert_eq!(Fraction::new(1, 2), Some(Fraction::from(1) / 2));\nassert_eq!(Fraction::new(50, 100), Fraction::new(1, 2));\nassert_eq!(Fraction::try_from(0.5).unwrap(), Fraction::new(1, 2).unwrap());\n/// - compare\nassert!(Fraction::new(1, 2).unwrap() == Fraction::new(1, 2).unwrap());\nassert!(Fraction::new(1, 2).unwrap() \u003e= Fraction::new(1, 2).unwrap());\nassert!(Fraction::new(1, 2).unwrap() \u003e Fraction::new(1, 3).unwrap());\nassert!(Fraction::new(1, 2).unwrap() \u003c= Fraction::new(1, 2).unwrap());\nassert!(Fraction::new(1, 2).unwrap() \u003c Fraction::new(2, 3).unwrap());\nassert!(Fraction::new(1, 2).unwrap() != Fraction::new(1, 3).unwrap());\n/// - calculate\nassert_eq!(Fraction::new(-1, 2).unwrap().abs(), Fraction::new(1, 2).unwrap());\nassert_eq!(Fraction::new(1, 3).unwrap() + Fraction::new(1, 6).unwrap(),\n           Fraction::new(1, 2).unwrap());\nassert_eq!(Fraction::new(1, 3).unwrap() / Fraction::new(2, 3).unwrap(),\n           Fraction::new(1, 2).unwrap());\nassert_eq!(Fraction::new(3, 2).unwrap().div_euclid(Fraction::from(1)), 1);\nassert_eq!(Fraction::new(1, 3).unwrap() * Fraction::new(3, 2).unwrap(),\n           Fraction::new(1, 2).unwrap());\nassert_eq!(-Fraction::new(-1, 2).unwrap(), Fraction::new(1, 2).unwrap());\nassert_eq!(Fraction::new(1, 2).unwrap().pow(2), Fraction::new(1, 4).unwrap());\nassert_eq!(Fraction::new(3, 2).unwrap() % Fraction::from(1),\n           Fraction::new(1, 2).unwrap());\nassert_eq!(Fraction::new(3, 2).unwrap().rem_euclid(Fraction::from(1)),\n           Fraction::new(1, 2).unwrap());\nassert_eq!(Fraction::new(3, 2).unwrap() - Fraction::from(1),\n           Fraction::new(1, 2).unwrap());\n```\n\nDevelopment\n-----------\n\n### Bumping version\n\n#### Preparation\n\nInstall\n[bump2version](https://github.com/c4urself/bump2version#installation).\n\n#### Pre-release\n\nChoose which version number category to bump following [semver\nspecification](http://semver.org/).\n\nTest bumping version\n\n```bash\nbump2version --dry-run --verbose $CATEGORY\n```\n\nwhere `$CATEGORY` is the target version number category name, possible\nvalues are `patch`/`minor`/`major`.\n\nBump version\n\n```bash\nbump2version --verbose $CATEGORY\n```\n\nThis will set version to `major.minor.patch-alpha`.\n\n#### Release\n\nTest bumping version\n\n```bash\nbump2version --dry-run --verbose release\n```\n\nBump version\n\n```bash\nbump2version --verbose release\n```\n\nThis will set version to `major.minor.patch`.\n\n### Running tests\n\nInstall dependencies\n\n```bash\npython -m pip install -r requirements-tests.txt\n```\n\nPlain\n\n```bash\npytest\n```\n\nInside `Docker` container:\n\n- with `CPython`\n  ```bash\n  docker-compose --file docker-compose.cpython.yml up\n  ```\n- with `PyPy`\n  ```bash\n  docker-compose --file docker-compose.pypy.yml up\n  ```\n\n`Bash` script:\n\n- with `CPython`\n  ```bash\n  ./run-tests.sh\n  ```\n  or\n  ```bash\n  ./run-tests.sh cpython\n  ```\n\n- with `PyPy`\n  ```bash\n  ./run-tests.sh pypy\n  ```\n\n`PowerShell` script:\n\n- with `CPython`\n  ```powershell\n  .\\run-tests.ps1\n  ```\n  or\n  ```powershell\n  .\\run-tests.ps1 cpython\n  ```\n- with `PyPy`\n  ```powershell\n  .\\run-tests.ps1 pypy\n  ```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flycantropos%2Frithm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flycantropos%2Frithm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flycantropos%2Frithm/lists"}