rfcs
rfcs copied to clipboard
Introduce new numerics
Partially related to:
- https://github.com/ponylang/rfcs/issues/168
- https://ponylang.zulipchat.com/#narrow/stream/192795-contribute-to.20Pony/topic/math.20lib
- https://ponylang.zulipchat.com/#narrow/stream/192795-contribute-to.20Pony/topic/How.20OO.20to.20go.3F.20.28was.20math.20lib.29
- https://ponylang.zulipchat.com/#narrow/stream/189985-beginner-help/topic/.E2.9C.94.20BigDecimal
Is there a reason to tie these different packages together? Would there be something we lose by discussing each individually?
Is there a reason to tie these different packages together? Would there be something we lose by discussing each individually?
I expect that you mean to suggest creation of discrete RFCs. As I answered for the "primary goals" comment for clarification, this RFC is meant to "expand" math is two ways. The first is to expand by providing structure, the second by providing functionality. If we want to make this RFC only the former, then I open RFCs for each subpackage that is fine by me. I thought opening with the initial additions as discussed (a long time ago) in Zulip was "better" than breaking it up without any discussion as to how we want to move towards a more expanded math package.
@rhagenson if these aren't tried to one another, I think that an RFC for each would be good.
I would focus on adding support for things like Complex numbers, Rational numbers, and those because the design issues for each of those is worthy of individual RFCs.
I'm not even sure that Rational numbers should go in math
. Math to be is more about "algos and processes" like "matrix multiplication" etc and not so much about things like complex or rational numbers. I'd seriously consider having rational numbers be their own top-level package. Ditto complex.
And fairly reasonable argument could be made for Arbitrary precision numbers to go into builtin. I think we would decide not to, but the argument could reasonably be made based on consistency of F32 and friends being there.
I am not against breaking this RFC into pieces, but wanted to present all the initial pieces at once. I am personally in favor of the addition functionality discussed here being outside of builtin since it will rely on builtin, but builtin will not rely on any of the suggested additions.
During Sync on 2022-03-01 I wrote down the following notes for how to improve this RFC:
- [x] Add implementation details; for example, what does a
Rational
look like internally? - [x] Add motivation for having canonical implementation for these types; addressing having interoperability of numerics across the Pony ecosystem
- [x] Mention intention to be compliant with existing numeric traits such as Real, Integer, etc
- [x] As an external reference, Haskell was noted as having a strong numerics hierarchy
@SeanTAllen Would me switching this to a draft PR prevent the discuss during sync label from being reapplied? I have doubts that I will get all the updates done before next Sync in time for folks to review the changes. I have no issue with more reviews/comments/discussion, but want to prevent issues of this RFC continually reappearing for Sync with only small or in-progress edits.
My current plan is:
- [x] Add top-down mermaid graph for the numeric type hierarchy as we have it today
- [x] Add top-down mermaid graph for the numeric type hierarchy with these new types included
- [ ] Fix the typing errors for at least
Rational
(I have a comment in the example implementation in the most recent commit)
Would me switching this to a draft PR prevent the discuss during sync label from being reapplied?
No.
See https://github.com/ponylang/rfcs/blob/main/.github/workflows/add-discuss-during-sync.yml#L3 for events that cause the label to be added.
- [x] Add BigFloat numeric to mermaid chart
- [x] Add Complex parameterized on Real
- [x] Add Rational parameterized on Integer
- [x] Discuss breaking this RFC into smaller dedicated RFCs concerning
- Adding numeric types to builtin
- Introducing new math functionality as suggested in this RFC (e.g., having a Constant primitive)
On Sync 2022-03-08, we discussed breaking this RFC into smaller dedicated RFCs with this RFC/PR specifically becoming a "Introduce new numerics; Rational, BigInt, BigFloat, Complex" and splitting the other content off to better allow us to discuss the merits of each addition/change.
I'm in favor of breaking this apart into different RFCs.
Apologies about temporarily closing this -- I tried changing the name of the expand-math
branch to add-numerics
and I guess that is not a thing I can do without forcing this PR to close.
Notes from Sync 2022-03-15:
- [ ] Update Unresolved Questions w/ details -- this RFC is the high-level overview of how the types fit into the numeric hierarchy, but discrete RFC for each numeric is needed providing complete implementation details
- [ ] Move suggestion out of
builtin
into newnumerics
package
I find this RFC very confusing as written. I don't understand what large sections are attempting to convey. I think I'm going to need someone to walk me through it as at the moment, I'm not really sure how to even phrase my "I don't understand" statements.
I'd like to see this broken apart further into an RFC for where Rational and Complex fit with the existing numerics hierarchy and a separate discussion of the best way to implement "Big" numerics. There are rather complicated issues that appear to apply to only "the bigs" that I think will take some time to resolve and during that time we can probably agree to how Rational and Complex will fit in with the existing, do detailed RFCS for each and implement them before the questions around "the bigs" are resolved.
Any thoughts on the possibility of having builtin complex primitive types? I think the RFC is proposing that all complex values will be object instances, which seems like it would be troublesome in various use-cases. For instance, I'm working on signal processing in Pony and have an actor that produces a stream of Vector[U8C]
s from RTL-SDR hardware. I'm currently defining type U8C is U16
, which gives me a complex type that matches C's representation of the same, so I can use C libraries that do vector processing on complex values.
C11 standard says:
Each complex type has the same representation and alignment requirements as an array type containing exactly two elements of the corresponding real type; the first element is equal to the real part, and the second element to the imaginary part, of the complex number.
libvolk (C library for vector operations) defines the following:
typedef char complex lv_8sc_t
typedef short complex lv_16sc_t
typedef long complex lv_32sc_t
typedef long long complex lv_64sc_t
typedef float complex lv_32fc_t
typedef double complex lv_64fc_t
In Pony, I imagine types like:
primitive I8C is SignedIntegerComplex[I8C]
primitive I16C is SignedIntegerComplex[I16C]
primitive I32C is SignedIntegerComplex[I32C]
primitive I64C is SignedIntegerComplex[I64C]
primitive I128C is SignedIntegerComplex[I128C]
primitive U8C is UnsignedIntegerComplex[U8C]
primitive U16C is UnsignedIntegerComplex[U16C]
primitive U32C is UnsignedIntegerComplex[U32C]
primitive U64C is UnsignedIntegerComplex[U64C]
primitive U128C is UnsignedIntegerComplex[U128C]
primitive F32C is FloatingPointComplex[F32C]
primitive F64C is FloatingPointComplex[F64C]
@adrianboyko Since I am the author on this RFC, I will chime in.
Any thoughts on the possibility of having builtin complex primitive types?
I am not against it outright because I do not know what all that would entail. However, this RFC will be refined (when I have time) to propose the higher level aspects of what numerics we wish to introduce. Which will then be followed by specific RFCs for the structure and implementation of those specific numerics. That is to say, how complex numerics are implemented is critical to their successful adoption and definitely needs to be a part of the RFC on their implementation.
The idea of primitive complex types was discussed a bit on the sync call.
The advantage of not having an extra object allocation is a great one.
To make that idea work, they would need to be in the builtin
package and would likely need many of their methods to be implemented as compiler_intrinsic
. This would be possible, but in my opinion it's not ideal.
In my opinion, this would be a good use case for struct-like value types, which I have discussed a bit in the past (and implemented in the Savi compiler for prototyping). The basic premise is that it would be a new kind of Pony type declaration that is declared just like a class
, but can only have let
fields (no var
fields) - and at runtime it behaves like a tuple (no object allocation, unless it gets "boxed" into an abstract type).
Having a "struct-like value type" like this would allow for avoiding the extra object allocation for the complex numeric types, as well as anything similar that others wanted to build in user-defined libraries. It also would solve the "newtype" use case discussed in #65. It would also help use cases where performance-sensitive code is currently using tuples for performance reasons where they would otherwise prefer to use classes.