DEV Community

Cover image for From C# to Rust: Porting MathFlow to Create MathCore - A Symbolic Math Library Journey
Berkant
Berkant

Posted on

From C# to Rust: Porting MathFlow to Create MathCore - A Symbolic Math Library Journey

# From C# to Rust: Building a Symbolic Math Library πŸš€

Hey DEV community! Today I want to share my journey of porting a symbolic math library from C# to Rust, and what I learned along the way.

## πŸ“– The Story

Last year, I built MathFlow - a symbolic math library for C#. It worked great, but I was curious about Rust's performance claims. So I decided to rebuild it as
MathCore in Rust.

The results? Mind-blowing! 🀯

## 🎯 Quick Comparison









πŸ”· C# (MathFlow) πŸ¦€ Rust (MathCore)


  var expr = MathExpression
      .Parse("x^2 + 2*x + 1");

  var derivative = expr
      .Differentiate("x");

  var result = expr
      .Evaluate(new { x = 5 });

  let expr = MathCore::parse(
      "x^2 + 2*x + 1"
  )?;

  let derivative = MathCore::differentiate(
      &expr, "x"
  )?;

  let result = math.calculate(
      &expr, &[("x", 5.0)]
  )?;

⚑ Performance Results

I was shocked by these numbers:

| Operation | C# (MathFlow) | Rust (MathCore) | Difference |
|------------------|---------------|-----------------|----------------|
| Parse Expression | 245 ¡s | 89 ¡s | 2.7x faster ✨ |
| Differentiate | 1,230 ¡s | 456 ¡s | 2.7x faster ✨ |
| Solve Equation | 890 Β΅s | 234 Β΅s | 3.8x faster πŸš€ |
| Memory Usage | 847 MB | 124 MB | 6.8x less 🎯 |


πŸ’‘ Key Differences I Discovered

1️⃣ Error Handling

  C# Way (Exceptions):
  try {
      var result = MathExpression.Parse("invalid");
  } catch (ParseException e) {
      Console.WriteLine($"Oops: {e.Message}");
  }

  Rust Way (Result Type):
  match MathCore::parse("invalid") {
      Ok(expr) => println!("Success!"),
      Err(e) => println!("Oops: {}", e),
  }

πŸ’­ Insight: Rust forces you to handle errors. No more surprise crashes in production!


2️⃣ Memory Management

C#:

  • βœ… Garbage collector handles everything
  • ❌ Random GC pauses
  • ❌ Unpredictable performance

Rust:

  • βœ… Predictable performance
  • βœ… No GC pauses
  • ❌ Must think about ownership

3️⃣ Real-World Example

Let's solve a physics problem - projectile motion with air resistance:


  // Calculate trajectory
  var equation = @"
      y = v0*sin(ΞΈ)*t - 
          0.5*g*t^2
  ";

  var solver = new MathEngine();
  var trajectory = solver
      .Parse(equation)
      .Substitute(new {
          v0 = 100,
          ΞΈ = Math.PI/4,
          g = 9.81
      });

  // Calculate trajectory
  let equation = "
      y = v0*sin(ΞΈ)*t - 
          0.5*g*t^2
  ";

  let math = MathCore::new();
  let trajectory = math
      .calculate(equation, &[
          ("v0", 100.0),
          ("ΞΈ", PI/4.0),
          ("g", 9.81),
      ])?;

🎨 Architecture Evolution

From OOP to Functional

  C# (Object-Oriented):
  public abstract class Expression {
      public abstract double Evaluate();
  }

  public class AddExpr : Expression {
      private Expression left, right;

      public override double Evaluate() {
          return left.Evaluate() + right.Evaluate();
      }
  }

  Rust (Algebraic Data Types):
  enum Expr {
      Number(f64),
      Add(Box<Expr>, Box<Expr>),
  }

  fn evaluate(expr: &Expr) -> f64 {
      match expr {
          Expr::Number(n) => *n,
          Expr::Add(l, r) => evaluate(l) + evaluate(r),
      }
  }

🎯 Why this matters: Pattern matching eliminated entire class hierarchies!


πŸš€ Cool Features in Both

Features Comparison

| Feature | MathFlow (C#) | MathCore (Rust) |
|--------------------------|---------------|-----------------|
| Symbolic Differentiation | βœ… | βœ… |
| Equation Solving | βœ… | βœ… |
| Matrix Operations | βœ… | βœ… |
| Complex Numbers | βœ… | βœ… |
| Arbitrary Precision | βœ… | βœ… |
| Parallel Computation | βœ… Tasks | βœ… Rayon |
| WASM Support | ⏳ Coming | βœ… Ready |
| FFT | βœ… | βœ… |


πŸ“¦ Try Them Out!

For .NET Developers:

dotnet add package MathFlow

  using MathFlow;

  var math = new MathEngine();
  var derivative = math.Differentiate("sin(x^2)", "x");
  Console.WriteLine(derivative); // Output: 2*x*cos(x^2)

For Rust Developers:

cargo add mathcore

  use mathcore::MathCore;

  fn main() {
      let derivative = MathCore::differentiate("sin(x^2)", "x").unwrap();
      println!("{}", derivative); // Output: 2*x*cos(x^2)
  }

πŸ€” Which Should You Use?

Choose MathFlow (C#) if you:

  • πŸ”· Are building .NET applications
  • πŸ”· Use Unity for game development
  • πŸ”· Want fastest development time
  • πŸ”· Prefer familiar OOP patterns

Choose MathCore (Rust) if you:

  • πŸ¦€ Need maximum performance
  • πŸ¦€ Want to compile to WASM
  • πŸ¦€ Build system-level tools
  • πŸ¦€ Care about memory efficiency

πŸ“ˆ What I Learned

  1. Rust's ownership model prevents entire categories of bugs
  2. Pattern matching can replace complex OOP hierarchies
  3. Zero-cost abstractions are real - high-level Rust code is FAST
  4. Both languages have their sweet spots

πŸ”— Links & Resources

MathFlow (C#)

https://github.com/Nonanti/MathFlow
https://nuget.org/packages/MathFlow

MathCore (Rust)

https://github.com/Nonanti/mathcore
https://crates.io/crates/mathcore
https://docs.rs/mathcore


πŸ’¬ Let's Discuss!

Have you ported a project between languages? What was your experience?

Drop a comment below! πŸ‘‡


If you found this helpful, consider giving the repos a ⭐!

Happy coding! πŸš€

Top comments (0)