Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Complex number support #752

Open
standarddeviant opened this issue Aug 5, 2023 · 4 comments
Open

Complex number support #752

standarddeviant opened this issue Aug 5, 2023 · 4 comments

Comments

@standarddeviant
Copy link

standarddeviant commented Aug 5, 2023

In the docs, the numeric types are INT, FLOAT, or Decimal. I'm wondering if it's aligned with the goals of the rhai project to add support for a Complex type that defaults to storing real and imaginary components as (2) f64 fields.

I'm working on a REPL that automatically loads rhai-sci, and wondering how complex matrix operations might work, and thinking it might be nice if a Complex number type was eventually built-in to rhai. There's already complex number support in nalgebra, which I believe rha-sci depends on:

Numpy and MATLAB both use "1i" or "1j" to represent an imaginary component, and this seems like good syntax - i.e. "let a = 2.0 + 1j * 3.5" would create a complex number. There would have to be some associated functions for arithmetic, sine, cosine, exponentials, etc.

Does that sound like a reasonable idea? I'm interested to prototype this and submit a PR. Any pointers on where to start or things to look for are appreciated.

@schungx
Copy link
Collaborator

schungx commented Aug 6, 2023

Currently there is nothing to prevent adding a complex number type as an add-on package, including complex versions of common math functions.

To make it efficient, however, it would probably be best to be built in, which means consider the following issues:

  1. Data storage. Right now a Dynamic is roughly two 64-bit word. Technically speaking, it is OK to pack a complex number with two f32 numbers... but not a complex number with two f64 (which would require Dynamic to be larger than 128-bit). Therefore, if we're handling f64 complex numbers, then the only option to to have allocations for each number... although it would be more efficient than the double-allocation of a custom type. Still, we're incurring an allocation for each instance of the complex number.

  2. Syntax: a simple expression like 2.0 + 1i * 3.5 can be interpreted two ways... and it breaks Rhai's operator precedences if we treat complex numbers are a tight unit. Do we force the user to write (2.0 + 1i) * 3.5? That would be easy to make mistakes.

Without a special syntax, it would be awkward to work with complex numbers, as you need to use constructor functions all the time...

@standarddeviant
Copy link
Author

For scientific applications, it might be suitable to have a special type for a larger complex matrices or ndarrays, and then have a custom type for a complex scalar. I need to look more closely at the documentation of custom types and how rhai-sci handles any custom types.

That's a good point about the syntax. I don't understand the parser, but it seems like the parser might follow operator precedence in the example you gave. It seems like

2.0 + 1i * 3.5

Would parse as
(float(2)) + (complex(0, 1) * float(3.5))

Then (float(2)) + (complex(0, 3.5))

Then (complex(2, 3.5))

That requires handling arithmetic types between a complex type and int/float. Is filling out those arithmetic functions between complex and float (for example) easily achievable if the complex scalar is in an add-on package?

@schungx
Copy link
Collaborator

schungx commented Aug 9, 2023

It would be difficult to alter the built-in precedence values for different math operators... and definitely difficult to have different precedence values for different cases, for example:

1 + 2 * 3      // should be 1 + (2 * 3)

1 + 2i * 3     // should be (1 + 2i) * 3 ?

Or should we force all complex literals to use parentheses?

(1 + 2i) * 3    // always use parens

@schungx
Copy link
Collaborator

schungx commented Aug 28, 2023

Just thinking about this some more, an easy-to-use complex number system should also have overloads for * acting as a conjugate?

let x = 42 + 99i;

let y = x*;    // conjugate

But how to do this without conflicting with the * operator is another issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants