#finite-fields #polynomial #arithmetic #toy #language #repl #expression

bin+lib polenta

A toy language about polynomials over finite-fields

2 releases

0.1.1 Sep 17, 2024
0.1.0 Sep 17, 2024

#1776 in Math

MIT license

29KB
532 lines

Polenta

Crates.io Version GitHub Actions Workflow Status Crates.io License

Polenta is a toy polynomial arithmetic language, and everything is a polynomial. As such, it is more suited towards having fun instead of having performance.

Features

  • Polynomial arithmetic using lambdaworks
  • REPL to play around with
  • let and assert expressions
  • prove and commit expressions

The project mostly started to learn more about Pest, and it is a lovely project! See https://pest.rs for more!

Installation

You can add the library with:

cargo add polenta

You can install the REPL with:

cargo install polenta --bin repl --features="repl"

Usage

In this section we go over what can be done with Polenta.

All code shown below are valid Polenta code. To follow along, you can use the REPL installed above!

Statements

You can use Polenta as a calculator-over-field.

> 10 - 2^3 * 2;
18446744069414584315

However, you should keep in mind that all operations are defined over the field, so division might not always work as you expect:

> 1 / 2; // some number x such that 2*x = 1, not 0.5!
9223372034707292161

Polenta supports single line comments using //, as shown above.

Creating a Polynomial

A polynomial is created by specifying its terms.

> let P(x) = 3*x^2 + 5;
3*x^2 + 5

Behind the scenes all terms are considered a monomial, and they are composed together. As such, you can repeat a term with the same degree and the result will have them added up:

> let P(x) = 3*x^2 + 2*x^2 + 1*x^2;
6*x^2
> let Q(x) = 5*x - 5*x + 1;
1

You can also multiply polynomials:

> let P(x) = (x + 1)*(x + 2)*(x + 4);
x^3 + 7*x^2 + 14*x + 8

You can create a polynomial from an existing one:

> let P(x) = 3*x;
3*x
> let Q(x) = P^2 + 2*P;
9*x^2 + 6*x

Shadowing is allowed:

> let P(x) = 3*x;
3*x
> let P(x) = 3*P + 5;
9*x + 5

You can use an identifier within a polynomial, but if the identifier has the same name as the term, it will be ignored.

> let t = 2;
> let x = 5;
> let P(x) = x^t + 2*x;
x^2 + 2*x

Equality

Polenta has == and != operators that return either a 1 or 0 based on the equality.

> 2 == 3
0
> let P(x) = 2*x
2*x
> let Q(x) = 3*x - x
2*x
> P == Q
1

Evaluating a Polynomial

Evaluation is achieved using a binary operation @, so that P@2 means "evaluate polynomial P at point 2.

> let P(x) = 3*x;
3*x
> let z = P@3;
9
> let Q(x) = x^z + z*x;
x^9 + 9*x

Remember that everything is a polynomial in Polenta, so you could evaluate a number as well. Evaluation will not have an effect because a number is treated as a constant polynomial.

> 4@2
4

Since evaluation is a binary operation, you can chain them together:

> let P(x) = 3*x + 1;
3*x + 1
> let Q(x) = x/2;
9223372034707292161*x
> Q@P@Q@P@3; // Q(P(Q(P(3))))
8

Assertions

You can make assertions within Polenta for safety, where a failed assertion throws an AssertionError. An assertion fails if the expression that they are given is a zero polynomial.

> assert 1
1
> assert 0
  × Assertion Failed

> assert 43
43

Errors in REPL

While using REPL, if there is an error you will see it on screen with clear logs.

> let x = idontexist;
  × Unknown Identifier: idontexist
> 5/0;
  × Division by Zero
> let a = ++syntaxerror--;
  × Syntax Error
   ╭─[input:1:9]
 1 │ let a = ++syntaxerror--;
   ·
   ╰────
  help: Expected one of [expr], got []

Testing

Run all tests with:

cargo test

License

Polenta is MIT licensed.

Dependencies

~7–19MB
~214K SLoC