{"id":18010182,"url":"https://github.com/p-e-w/savage","last_synced_at":"2025-05-16T10:03:19.346Z","repository":{"id":47218698,"uuid":"432637329","full_name":"p-e-w/savage","owner":"p-e-w","description":"A primitive computer algebra system","archived":false,"fork":false,"pushed_at":"2023-04-29T15:45:15.000Z","size":164,"stargazers_count":577,"open_issues_count":16,"forks_count":11,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-09T04:04:44.719Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/p-e-w.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2021-11-28T06:31:25.000Z","updated_at":"2025-03-29T14:48:48.000Z","dependencies_parsed_at":"2024-10-30T02:44:03.468Z","dependency_job_id":null,"html_url":"https://github.com/p-e-w/savage","commit_stats":{"total_commits":50,"total_committers":2,"mean_commits":25.0,"dds":0.07999999999999996,"last_synced_commit":"24e25a6a5add3a36fce7c50c89b6d38739948506"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p-e-w%2Fsavage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p-e-w%2Fsavage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p-e-w%2Fsavage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/p-e-w%2Fsavage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/p-e-w","download_url":"https://codeload.github.com/p-e-w/savage/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253377267,"owners_count":21898938,"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","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":[],"created_at":"2024-10-30T02:13:16.527Z","updated_at":"2025-05-16T10:03:19.296Z","avatar_url":"https://github.com/p-e-w.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Savage Computer Algebra System\n\nSavage is a new computer algebra system written from scratch in pure Rust.\nIts goals are correctness, simplicity, and usability, in that order.\nThe entire system compiles to a single, dependency-free executable just\n2.5 MB in size. While that executable will of course grow as Savage matures,\nthe plan is to eventually deliver a useful computer algebra system in 5 MB\nor less.\n\n![Screenshot](https://user-images.githubusercontent.com/2702526/158006796-7d3aad2a-217f-421a-b3f8-20498d32b0f0.png)\n\nThe name \"Savage\" is a reference/homage to [Sage](https://www.sagemath.org/),\nthe leading open-source computer algebra system. Since Sage already exists\nand works very well, it would make no sense to attempt to create a clone of it.\nInstead, Savage aims to be something of an antithesis to Sage: Where Sage is\na unified frontend to dozens of mathematics packages, Savage is a tightly-integrated,\nmonolithic system. Where Sage covers many areas of mathematics, including cutting-edge\nresearch topics, Savage will focus on the \"bread and butter\" math employed by\nengineers and other people who *use*, rather than develop, mathematical concepts.\nWhere Sage features amazingly sophisticated implementations of countless functions,\nSavage has code that is savagely primitive, getting the job done naively but correctly,\nwithout worrying whether the performance is still optimal when the input is\na million-digit number.\n\n**Savage is in early development and is not yet ready to be used for serious work.**\nIt is, however, ready to play around with, and is happily accepting contributions\nto move the project forward.\n\n\n## Features\n\nThis is what Savage offers **today:**\n\n* Arbitrary-precision integer, rational, and complex arithmetic\n* Input, simplification, and evaluation of symbolic expressions\n* First-class support for vectors and matrices, with coefficients being arbitrary expressions\n* REPL with syntax and bracket highlighting, persistent history, and automatic multi-line input\n* Macro-based system for defining functions with metadata and automatic type checking\n* [Usable as a library](#savage-as-a-library) from any Rust program\n\nThe following features are **planned,** with some of the groundwork already done:\n\n* User-defined variables and functions\n* Built-in help system\n* Many more functions from various areas of math\n* More powerful expression simplification\n* Jupyter kernel\n\nBy contrast, the following are considered **non-features** for Savage,\nand there are no plans to add them either now or in the future:\n\n* *Advanced/research-level mathematics:* As a rule of thumb, if it doesn't belong\n  in a typical undergraduate course, it probably doesn't belong in Savage.\n* *Physics/finance/machine learning/other areas adjacent to math:* The scope would\n  grow without bounds and that is exactly what Savage aims to avoid.\n* *Formal verification of implementations:* The required technologies aren't mature yet\n  and Savage is not a research project.\n* *Performance at the expense of simplicity:* Yes, I know that multiplication\n  can be done faster using some fancy Fourier tricks. No, I won't implement that.\n* *General-purpose programming:* Too complex, and not the focus of this project.\n* *File/network I/O:* Savage performs computations, nothing more and nothing less.\n  Functions have no side effects.\n* *Modules/packages/extensions/plugins:* The world is complicated enough.\n  Either something is built in, or Savage doesn't have it at all.\n* *GUI:* Although it's possible to create a GUI frontend backed by the `savage_core`\n  crate, there are no plans to do so within the Savage project itself.\n\n\n## Installation\n\nBuilding Savage from source requires [Rust](https://www.rust-lang.org/) **1.56 or later.**\nOnce a supported version of Rust is installed on your system, you only need to run\n\n```\ncargo install savage\n```\n\nto install the Savage REPL to your Cargo binary directory (usually `$HOME/.cargo/bin`).\nOf course, you can also just clone this repository and `cargo run` the REPL from the\nrepository root.\n\nIn the future, there will be pre-built executables for major platforms\navailable with every Savage release.\n\n\n## Tour\n\n### Arithmetic\n\nArithmetic operations in Savage have no precision limits (other than the amount\nof memory available in your system):\n\n```\nin: 1 + 1\nout: 2\n\nin: 1.1 ^ 100\nout: 13780.612339822270184118337172089636776264331200038466433146477552154985209\n5523076769401159497458526446001\n\nin: 3 ^ 4 ^ 5\nout: 373391848741020043532959754184866588225409776783734007750636931722079040617\n26525122999368893880397722046876506543147515810872705459216085858135133698280918\n73141917485942625809388070199519564042855718180410466812887974029255176680123406\n17298396574731619152386723046235125934896058590588284654793540505936202376547807\n44273058214452705898875625145281779341335214192074462302751872918543286237573706\n39854853194764169262638199728870069070138992565242971985276987492741962768110607\n02333710356481\n```\n\nResults are automatically printed in either fractional or decimal form,\ndepending on whether the input contained fractions or decimal numbers:\n\n```\nin: 6/5 * 3\nout: 18/5\n\nin: 1.2 * 3\nout: 3.6\n```\n\nThe variable `i` is predefined to represent the imaginary unit, allowing for\ncomplex numbers to be entered using standard notation:\n\n```\nin: (1 + i) ^ 12\nout: -64\n```\n\n### Linear algebra\n\nVectors and matrices are first-class citizens in Savage and support the standard\naddition, subtraction, multiplication, and exponentiation operators. Coefficients\ncan be arbitrary expressions:\n\n```\nin: [a, b] - [a, c]\nout: [0, b - c]\n\nin: [a, b, c] * 3\nout: [a * 3, b * 3, c * 3]\n\nin: [[1, 2], [3, 4]] * [5, 6]\nout: [17, 39]\n```\n\nDeterminants are evaluated symbolically:\n\n```\nin: det([[a, 2], [3, a]])\nout: a ^ 2 - 6\n```\n\n### Logic\n\nThe standard `\u0026\u0026`, `||`, `!`, and comparison operators are available. Savage\nautomatically evaluates many tautologies and contradictions, even in the presence\nof undefined variables:\n\n```\nin: a \u0026\u0026 true\nout: a\n\nin: a || true\nout: true\n\nin: a || !a\nout: true\n\nin: a \u003c a\nout: false\n```\n\n### Number theory\n\nVerify that the Mersenne number *M\u003csub\u003e31\u003c/sub\u003e* is a prime number:\n\n```\nin: is_prime(2^31 - 1)\nout: true\n```\n\nCompute the ten millionth prime number:\n\n```\nin: nth_prime(10^7)\nout: 179424673\n```\n\nCompute the number of primes up to ten million:\n\n```\nin: prime_pi(10^7)\nout: 664579\n```\n\nThese functions for dealing with prime numbers are powered by the ultra-fast\n[`primal`](https://crates.io/crates/primal) crate. Many more functions from\nnumber theory will be added to Savage in the future.\n\n\n## Savage as a library\n\nAll of Savage's actual computer algebra functionality is contained in the\n[`savage_core`](https://crates.io/crates/savage_core) crate. That crate exposes\neverything necessary to build software that leverages symbolic math capabilities.\nAssuming `savage_core` has been added as a dependency to a crate's `Cargo.toml`,\nit can be used like this:\n\n```rust\nuse std::collections::HashMap;\n\nuse savage_core::{expression::Expression, helpers::*};\n\nfn main() {\n    // Expressions can be constructed by parsing a string literal...\n    let lhs = \"det([[a, 2], [3, a]])\".parse::\u003cExpression\u003e().unwrap();\n    // ... or directly from code using helper functions.\n    let rhs = pow(var(\"a\"), int(2)) - int(6);\n\n    let mut context = HashMap::new();\n    // The context can be used to set the values of variables during evaluation.\n    // Change \"b\" to \"a\" to see this in action!\n    context.insert(\"b\".to_owned(), int(3));\n\n    assert_eq!(lhs.evaluate(context), Ok(rhs));\n}\n```\n\nPlease note that at this point, the primary purpose of the `savage_core` crate is\nto power the Savage REPL, so any use by third-party crates should be considered\nsomewhat experimental. Note also that like the rest of Savage, `savage_core` is\nlicensed under the terms of the [AGPL](LICENSE), which imposes conditions on any\ndependent software that go beyond what is required by the more common permissive\nlicenses. Make sure you understand the AGPL and its implications before adding\n`savage_core` as a dependency to your crate.\n\n\n## Acknowledgments\n\nSavage stands on the shoulders of the giant that is the Rust ecosystem. Among the\nmany third-party crates that Savage relies on, I want to highlight two that play\na particularly important role:\n\n* [`num`](https://crates.io/crates/num) is the fundamental crate for all numeric\n  computations in Savage. It provides the crucial `BigInt` type that enables\n  standard arithmetic operations to be performed with arbitrary precision.\n  `num`'s code is of high quality and extremely well tested.\n* [`chumsky`](https://crates.io/crates/chumsky) is the magic behind Savage's expression\n  parser. I have looked at every parser crate currently available and found Chumsky's\n  API to be by far the most intuitive. Furthermore, Chumsky's author is highly\n  responsive on the issue tracker, and has personally helped me understand and resolve\n  two major issues that arose during the development of Savage's parser.\n\n\n## License\n\nCopyright \u0026copy; 2021-2022  Philipp Emanuel Weidmann (\u003cpew@worldwidemann.com\u003e)\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published by\nthe Free Software Foundation, either version 3 of the License, or\n(at your option) any later version.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program.  If not, see \u003chttps://www.gnu.org/licenses/\u003e.\n\n**By contributing to this project, you agree to release your\ncontributions under the same license.**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp-e-w%2Fsavage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fp-e-w%2Fsavage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fp-e-w%2Fsavage/lists"}