ElectrifyPro / cas-rs

An opinionated computer algebra system written in Rust, used by CalcBot.
MIT License
35 stars 3 forks source link

Problem when truncating integer to a multiple #1

Open jafioti opened 5 months ago

jafioti commented 5 months ago

I am truncating an integer to a multiple of 256 by doing ((s + 255) / 256) * 256. Unfortunately this results in Add([Primary(Integer(255)), Primary(Symbol("s"))]) as the output when simplified, which isn't correct in this case since it undoes the truncation.

Is there a way to preserve this functionality? Or prevent it from being reduced by the simplify function?

jafioti commented 5 months ago

Code to reproduce:

use cas_compute::{
    primitive::int,
    symbolic::{
        expr::{Expr, Primary},
        simplify,
    },
};
use cas_parser::parser::{ast::Expr as AstExpr, Parser};

fn main() {
    let mut parser = Parser::new("((s + 255) / 256) * 256");
    let ast_expr = parser.try_parse_full::<AstExpr>().unwrap();
    let simplified = simplify(&ast_expr.into());

    println!("{:?}", simplified);
}
jafioti commented 5 months ago

@ElectrifyPro I think the best approach here would be to support Mod, which would allow us to do s - (s % 256) instead.

I'd love to help add this to the library. Where would you suggest I start?

jafioti commented 5 months ago

Also quick question, would there be a way to support the following ops in a straightforward manner: Max, Min, And, Or, GreaterThanOrEqual, LessThan?

ElectrifyPro commented 5 months ago

Is there a way to preserve this functionality? Or prevent it from being reduced by the simplify function?

I think the best approach here would be to support Mod, which would allow us to do s - (s % 256) instead.

Also quick question, would there be a way to support the following ops in a straightforward manner: Max, Min, And, Or, GreaterThanOrEqual, LessThan?

As of now, the symbolic library unfortunately doesn't support any of these features, however they definitely will be supported in the future!

However, the numerical library does support all of these features; if it works for you, you could use:

use cas_compute::numerical::eval::Eval;
use cas_parser::parser::{ast::Expr, Parser};

fn main() {
    let mut parser = Parser::new("trunc(350, 256)"); // truncate 350 towards nearest multiple of 256
    let ast_expr = parser.try_parse_full::<Expr>().unwrap();
    let result = ast_expr.eval_default().unwrap();

    // prints: Integer(256)
    println!("{:?}", result);
}

I'd love to help add this to the library. Where would you suggest I start?

I'd appreciate any help! The code that handles many of the missing features you need is located here inside the from(expr: AstExpr) function. We'd need to add support for:

This would require extending the Expr type to support those operations, adding a Boolean variant to the Primary type, and extending the simplifier as well. There's absolutely no time pressure or anything of the sort; feel free to take a look if you're interested!

BilakshanP commented 2 months ago

I'd appreciate any help!

Hi, there! I really liked this project and would like to contribute. Though I am still making myself familiar with the code-base. I hope I'd be able to contribute for the better!