From 0d1e3ac755457b318c850690ce71d1dac5ba6245 Mon Sep 17 00:00:00 2001 From: Ellie Hermaszewska Date: Fri, 14 Feb 2025 15:19:56 +0800 Subject: [PATCH 1/5] move from slang/proposals --- ...21-abstract-algebra-interface-hierarchy.md | 347 ++++++++++++++++++ 1 file changed, 347 insertions(+) create mode 100644 proposals/021-abstract-algebra-interface-hierarchy.md diff --git a/proposals/021-abstract-algebra-interface-hierarchy.md b/proposals/021-abstract-algebra-interface-hierarchy.md new file mode 100644 index 0000000..3d674c6 --- /dev/null +++ b/proposals/021-abstract-algebra-interface-hierarchy.md @@ -0,0 +1,347 @@ +# SP #015: Abstract Algebra Interface Hierarchy + +This proposal introduces a hierarchy of algebraic structure interfaces in +Slang, providing a foundation for principled generic mathematical +operations. + +## Status + +Status: Design Review + +Implementation: N/A + +Author: Ellie Hermaszewska + +Reviewer: TBD + +## Background + +Currently, Slang lacks a formal way to express algebraic properties of types. +While basic arithmetic operations are supported, there's no standard vocabulary +to express a type's conformance to algebraic laws. This is particularly +relevant for graphics programming where we frequently work with a variety of +mathematical objects, each fulfilling different properties described by +abstract algebra, for example: + +- Vector spaces +- Quaternions +- Dual numbers +- Matrices +- Complex numbers + +Additionally, many types support only a subset of arithmetic operations. For +example: + +- Strings support concatenation (forming a monoid) but not subtraction +- Colors support addition and scalar multiplication but not division +- Matrices support multiplication but aren't always invertible +- Non-empty containers support concatenation (forming a semigroup) but lack an + identity element + +A single catch-all "Arithmetic" interface would be insufficient as it would +force types to implement operations that don't make mathematical sense + +A formal interface hierarchy allows us to: + +- Write generic code that works across multiple numeric types +- Clearly document mathematical properties +- Avoid forcing inappropriate operations on types + +## Related Work + +- Haskell: Extensive typeclass hierarchy (Semigroup, Monoid) + - Haskell does have a catch-all `Num` class, which is largely considered a + misfeature, and several third-party packages exist to rectify this with a + more nuanced abstract algebra hierarchy +- PureScript: Similar to Haskell but with stricter adherence to category theory + principles +- Rust: Traits for arithmetic operations (Add, Mul) +- Scala: Abstract algebra typeclasses in libraries like Spire + +## Proposed Approach + +Implement the following interfaces, replacing in part `__BuiltinArithmeticType` + +```slang +// Semigroup represents types with an associative addition operation +// Examples: Non-empty arrays (concatenation), Colors (blending) +interface Semigroup +{ + T operator+(T a, T b); // Associative addition +}; + +// Monoid adds an identity element to Semigroup +// Examples: float3(0), identity matrix, zero quaternion +interface Monoid : Semigroup +{ + static T zero(); // Additive identity +}; + +// Group adds inverse elements to Monoid +// Examples: Vectors under addition, Matrices under addition +interface Group : Monoid +{ + T operator-(); // Additive inverse +}; + +// CommutativeGroup ensures addition order doesn't matter +// Examples: Vectors, Colors (in linear space) +interface CommutativeGroup : Group +{ + // Enforces a + b == b + a +}; + +// Semiring adds multiplication with identity to Monoid +// Examples: Matrices, Quaternions +interface Semiring : Monoid +{ + T operator*(T a, T b); + static T one(); +}; + +// Ring combines CommutativeGroup with multiplication +// Examples: Dual numbers, Complex numbers +interface Ring : CommutativeGroup +{ + T operator*(T a, T b); + static T one(); +}; + +// CommutativeRing ensures multiplication order doesn't matter +// Examples: Complex numbers, Dual numbers +interface CommutativeRing : Ring +{ + // Enforces a * b == b * a +}; + +// EuclideanRing adds division with remainder +// Examples: Integers for texture coordinates +interface EuclideanRing : CommutativeRing +{ + T operator/(T a, T b); + T operator%(T a, T b); + uint norm(T a); +}; + +// DivisionRing adds multiplicative inverses +// Examples: Quaternions +interface DivisionRing : Ring +{ + T recip(); // Multiplicative inverse (named to avoid confusion with matrix inverse) +}; + +// Field combines CommutativeRing with DivisionRing +// Examples: Real numbers, Complex numbers +interface Field : CommutativeRing, DivisionRing +{ +}; +``` + +## Implementation notes + +Part of the scope of this work is to determine how close to this design we can +achieve and not break backwards compatability. Or, what elements of backwards +compatability we are willing to compromise on if any. + +## Interface Rationale + +Each interface has specific types that satisfy it but not more specialized +interfaces. A selection of non-normative examples. + +- Semigroup: Non-empty arrays/buffers under concatenation (no identity element) +- Monoid: Strings under concatenation (no inverse operation) +- Group: Square matrices under addition (multiplication isn't distributive) +- CommutativeGroup: Vectors under addition (no multiplication) +- Semiring: Boolean algebra (no additive inverses) +- Ring: Square matrices under standard operations (multiplication isn't + commutative) +- CommutativeRing: Dual numbers (no general multiplicative inverse) +- EuclideanRing: Integers (no multiplicative inverse) +- DivisionRing: Quaternions (multiplication isn't commutative) +- Field: Complex numbers, Real numbers (satisfy all field axioms) + +## Floating Point Considerations + +The algebraic laws described must account for floating point arithmetic +limitations: + +- Associativity is not exact: `(a + b) + c ≠ a + (b + c)` for some values +- Distributivity has rounding errors: `a * (b + c) ≠ (a * b) + (a * c)` + +Therefore, implementations should: + +- Consider operations "lawful" if they're within acceptable epsilon +- Document precision guarantees +- Consider NaN and Inf as special cases + +## Operator Precedence + +All operators maintain their existing precedence rules. For example: + +```slang +a + b * c // equivalent to a + (b * c) +``` + +## Literal Conversion Interfaces + +```slang +// Types that can be constructed from integer literals +interface FromInt +{ + static T fromInt(int value); +}; + +// Types that can be constructed from floating point literals +interface FromFloat +{ + static T fromFloat(float value); +}; +``` + +Design choices still TBD: + +- Handling of integer literals that exceed the target type's range +- Treatment of unsigned integer literals +- Conversion of double precision literals to single precision types +- Error reporting mechanisms for out-of-range values +- Whether to provide separate interfaces for different integer types (int32, + uint32, etc.) + +## Generic Programming + +This hierarchy enables generic algorithms that work with any type satisfying +specific algebraic properties: + +```slang +// Generic linear interpolation for any Field +T lerp(T a, T b, T t) +{ + return a * (T.one() - t) + b * t; +} + +// Generic accumulation for any Monoid +T sum(T[] elements) +{ + T result = T.zero(); + for(T elem in elements) + result = result + elem; + return result; +} + +// Generic matrix multiplication +matrix; mul( + a : matrix, + b : matrix +) +{ + // Implementation using only Ring operations +} + + +// Generic geometric transforms +Transform compose(Transform a, Transform b) +{ + // Implementation using Ring operations +} +``` + +## Alternatives Considered + +### More nuanced hierarchy + +We could go a little further an introduce structures such as a `Magma`, which +could be used to represent non-associative binary operations without an +identity element. This could be used for example for some color mixing, however +this has a major downside in that it defies programmer intuition that the `+` +operator is associative. + +### Operator Overloading Only + +We could rely solely on operator overloading without formal interfaces. +Rejected because: + +- Lawless, hard to reason about code +- Less clear documentation of mathematical properties +- Harder to write generic code with specific algebraic requirements + +### Leave this to a third party library + +These operations describe very fundamental aspects of the language, leaving +this to a third party library would risk incompatible interfaces arising. We +also have many higher level constructs already in the standard library which +will need to built upon some algebraic hierarchy. + +### Alternative: Heterogeneous Operation Types + +Similar to Rust's approach, we could allow operations to return different types than their inputs: + +```slang +interface Add +{ + associatedtype Output; + Output operator+(This, RHS); +} +``` + +This would enable operations like: + +```slang +extension matrix : Mul +{ + associatedtype Output = float3; + Output operator*(This a, Vector3 b) { /* ... */ } +} + +extension float : Add +{ + associatedtype Output = float3; + Output operator+(This a, float b) { /* ... */ } +} +``` + +This comes with some downsides however: + +- Non-injective type families (where multiple input type combinations could + produce the same output type) may lead to worse type inference. +- This flexibility, while powerful, introduces potential confusion about + operation semantics +- Most mathematical structures in abstract algebra assume operations are closed +- The rare cases where heterogeneous operations are needed can be served + by explicit conversion functions or dedicated methods. This can also be + served by implicit conversions. + +The benefits of simpler type inference and clearer algebraic semantics outweigh +the flexibility of heterogeneous operations. + +## Future Extensions + +Several potential extensions could enhance this algebraic hierarchy: + +- Vector Space Interface + + - Add dedicated interfaces for vector spaces over fields + - Include operations for scalar multiplication and inner products + - Support for normed vector spaces + +- Ordered Algebraic Structures + + - Introduce interfaces for ordered rings and fields + - Support comparison operators (<, >, <=, >=) + - Enable generic sorting and optimization algorithms + +- Lattice Structures + + - Add interfaces for lattices and boolean algebras + - Support min/max operations + - Interval arithmetic + +- Module Interface + + - Support for modules over rings + - Generalize vector space concepts + - Enable more generic linear algebra operations + +- Error Handling Extensions + - Refined error types for algebraic operations + - Optional bounds checking interfaces + - Overflow behavior specifications From d8026ef7b63124956203e0cb4d773902805773d1 Mon Sep 17 00:00:00 2001 From: Ellie Hermaszewska Date: Fri, 14 Feb 2025 15:56:54 +0800 Subject: [PATCH 2/5] correct names --- ...21-abstract-algebra-interface-hierarchy.md | 66 +++++++++---------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/proposals/021-abstract-algebra-interface-hierarchy.md b/proposals/021-abstract-algebra-interface-hierarchy.md index 3d674c6..73c26a0 100644 --- a/proposals/021-abstract-algebra-interface-hierarchy.md +++ b/proposals/021-abstract-algebra-interface-hierarchy.md @@ -63,78 +63,72 @@ A formal interface hierarchy allows us to: Implement the following interfaces, replacing in part `__BuiltinArithmeticType` ```slang -// Semigroup represents types with an associative addition operation +// IAdditive represents a semigroup, i.e. types with an associative addition +// operation // Examples: Non-empty arrays (concatenation), Colors (blending) -interface Semigroup +interface IAdditive { T operator+(T a, T b); // Associative addition }; -// Monoid adds an identity element to Semigroup +// IAdditiveIdentity represents an identity element on top of IAdditive, forming +// a monoid // Examples: float3(0), identity matrix, zero quaternion -interface Monoid : Semigroup +interface IAdditiveIdentity : IAdditive { static T zero(); // Additive identity }; -// Group adds inverse elements to Monoid +// ISubtractable adds inverse elements to IAdditiveIdentity, i.e. this is group // Examples: Vectors under addition, Matrices under addition -interface Group : Monoid +interface ISubtractable : IAdditiveIdentity { T operator-(); // Additive inverse }; -// CommutativeGroup ensures addition order doesn't matter -// Examples: Vectors, Colors (in linear space) -interface CommutativeGroup : Group -{ - // Enforces a + b == b + a -}; - -// Semiring adds multiplication with identity to Monoid -// Examples: Matrices, Quaternions -interface Semiring : Monoid +// ISemiring adds non-commutative multiplication with identity to IAdditiveIdentity, +// Examples: Natural numbers under addition and multiplication +interface ISemiring : IZero { T operator*(T a, T b); static T one(); }; -// Ring combines CommutativeGroup with multiplication -// Examples: Dual numbers, Complex numbers -interface Ring : CommutativeGroup +// IMultiplicative combines ISemiring with ISubtractable to form a ring. +// Examples: Square matrices +interface IMultiplicative : ISemiring, ISubtractable { - T operator*(T a, T b); - static T one(); }; -// CommutativeRing ensures multiplication order doesn't matter -// Examples: Complex numbers, Dual numbers -interface CommutativeRing : Ring +// ICommutativeRing enforces that multiplication is commutative +// Examples: Integers +interface ICommutativeRing : IMultiplicative { // Enforces a * b == b * a }; -// EuclideanRing adds division with remainder -// Examples: Integers for texture coordinates -interface EuclideanRing : CommutativeRing +// IDivisible adds a multiplicative inverse to IMultiplicative +// Examples: Quaternions +interface IDivisible : IMultiplicative { - T operator/(T a, T b); - T operator%(T a, T b); - uint norm(T a); + T recip(T x); // Multiplicative inverse (named to avoid confusion with matrix inverse) }; -// DivisionRing adds multiplicative inverses -// Examples: Quaternions -interface DivisionRing : Ring +// IRemainder adds division with remainder to ICommutativeRing +// Examples: Integers +interface IRemainder : CommutativeRing { - T recip(); // Multiplicative inverse (named to avoid confusion with matrix inverse) + T operator/(T a, T b); + T operator%(T a, T b); + uint norm(T a); }; -// Field combines CommutativeRing with DivisionRing +// IField combines ICommutativeRing with IDivisble // Examples: Real numbers, Complex numbers -interface Field : CommutativeRing, DivisionRing +interface IField : ICommutativeRing, IDivisible { }; + ``` ## Implementation notes From ee9284e71249cea595adb5d74983a73a01efdf49 Mon Sep 17 00:00:00 2001 From: Ellie Hermaszewska Date: Fri, 14 Feb 2025 15:57:03 +0800 Subject: [PATCH 3/5] rename interfaces --- ...21-abstract-algebra-interface-hierarchy.md | 170 +++++++++--------- 1 file changed, 90 insertions(+), 80 deletions(-) diff --git a/proposals/021-abstract-algebra-interface-hierarchy.md b/proposals/021-abstract-algebra-interface-hierarchy.md index 73c26a0..ce1dafa 100644 --- a/proposals/021-abstract-algebra-interface-hierarchy.md +++ b/proposals/021-abstract-algebra-interface-hierarchy.md @@ -1,8 +1,7 @@ -# SP #015: Abstract Algebra Interface Hierarchy +# SP #021: Abstract Algebra Interface Hierarchy This proposal introduces a hierarchy of algebraic structure interfaces in -Slang, providing a foundation for principled generic mathematical -operations. +Slang, providing a foundation for principled generic mathematical operations. ## Status @@ -29,17 +28,17 @@ abstract algebra, for example: - Matrices - Complex numbers -Additionally, many types support only a subset of arithmetic operations. For -example: +Additionally, many types support only a subset of arithmetic operations. For example: -- Strings support concatenation (forming a monoid) but not subtraction +- Strings support concatenation (forming a monoid (an additive identity + structure)) but not subtraction - Colors support addition and scalar multiplication but not division - Matrices support multiplication but aren't always invertible -- Non-empty containers support concatenation (forming a semigroup) but lack an - identity element +- Non-empty containers support concatenation (forming a semigroup) + but lack an identity element A single catch-all "Arithmetic" interface would be insufficient as it would -force types to implement operations that don't make mathematical sense +force types to implement operations that don't make mathematical sense. A formal interface hierarchy allows us to: @@ -60,99 +59,112 @@ A formal interface hierarchy allows us to: ## Proposed Approach -Implement the following interfaces, replacing in part `__BuiltinArithmeticType` +Implement the following interfaces, replacing in part `__BuiltinArithmeticType`: ```slang -// IAdditive represents a semigroup, i.e. types with an associative addition -// operation -// Examples: Non-empty arrays (concatenation), Colors (blending) +// IAdditive represents a semigroup - a set with an associative binary operation +// Properties: (a + b) + c = a + (b + c) +// Examples: Non-empty arrays (concatenation), Colors (blending), Positive integers (addition) interface IAdditive { - T operator+(T a, T b); // Associative addition + static This operator+(This a, This b); // Associative addition }; -// IAdditiveIdentity represents an identity element on top of IAdditive, forming -// a monoid -// Examples: float3(0), identity matrix, zero quaternion +// IAdditiveIdentity represents a monoid - a semigroup with an identity element +// Properties: zero() + a = a + zero() = a +// Examples: Arrays (empty array), Natural Numbers (0), Matrices (zero matrix) interface IAdditiveIdentity : IAdditive { - static T zero(); // Additive identity + static This zero(); // Additive identity }; -// ISubtractable adds inverse elements to IAdditiveIdentity, i.e. this is group -// Examples: Vectors under addition, Matrices under addition +// ISubtractable represents a group - a monoid with inverse elements +// Properties: a + (-a) = (-a) + a = zero() +// Examples: Integers, Real numbers, Vectors, Matrices under addition interface ISubtractable : IAdditiveIdentity { - T operator-(); // Additive inverse + static This operator-(This t); // Additive inverse + static This operator-(This a, This b); }; -// ISemiring adds non-commutative multiplication with identity to IAdditiveIdentity, -// Examples: Natural numbers under addition and multiplication -interface ISemiring : IZero +// IDistributive combines additive monoid with multiplicative monoid to form a +// semiring. +// Properties: Multiplication distributes over addition +// (a + b) * c = (a * c) + (b * c) +// c * (a + b) = (c * a) + (c * b) +// one() * a = a * one() = a +// Examples: Natural numbers, Matrices, Boolean algebra +interface IDistributive : IAdditiveIdentity { - T operator*(T a, T b); - static T one(); + static This operator*(This a, This b); // Multiplicative operation + static This one(); // Multiplicative identity }; -// IMultiplicative combines ISemiring with ISubtractable to form a ring. -// Examples: Square matrices -interface IMultiplicative : ISemiring, ISubtractable +// IMultiplicative combines semiring with additive group to form a ring +// Properties: All semiring properties plus additive inverses, multiplication +// may not be commutative. +// Examples: Integers, Square matrices, Quaternions +interface IMultiplicative : IDistributive, ISubtractable { }; -// ICommutativeRing enforces that multiplication is commutative -// Examples: Integers +// ICommutativeRing represents a ring where multiplication is commutative +// Properties: a * b = b * a +// Examples: Integers, Real numbers, Complex numbers interface ICommutativeRing : IMultiplicative { - // Enforces a * b == b * a + // Enforces a * b = b * a }; -// IDivisible adds a multiplicative inverse to IMultiplicative -// Examples: Quaternions +// IDivisible adds multiplicative inverses to a IDivible to form a division +// ring +// Properties: x * recip(x) = recip(x) * x = one() +// Examples: Quaternions, Real matrices (when invertible) interface IDivisible : IMultiplicative { - T recip(T x); // Multiplicative inverse (named to avoid confusion with matrix inverse) + static This recip(This x); // Multiplicative inverse + static This operator/(This a, This b); // Division }; -// IRemainder adds division with remainder to ICommutativeRing -// Examples: Integers -interface IRemainder : CommutativeRing +// IRemainder adds Euclidean division properties to a commutative ring +// Properties: a = (a / b) * b + (a % b) where norm(a % b) < norm(b) +// Examples: Integers, Polynomials +interface IRemainder : ICommutativeRing { - T operator/(T a, T b); - T operator%(T a, T b); - uint norm(T a); + static This operator%(This a, This b); // Remainder + static uint norm(This a); // Absolute value for remainder comparison }; -// IField combines ICommutativeRing with IDivisble -// Examples: Real numbers, Complex numbers +// IField represents a commutative ring where every non-zero element has a multiplicative inverse +// Properties: All commutative ring properties plus multiplicative inverses +// Examples: Real numbers, Complex numbers, Rational numbers interface IField : ICommutativeRing, IDivisible { }; - ``` ## Implementation notes Part of the scope of this work is to determine how close to this design we can -achieve and not break backwards compatability. Or, what elements of backwards -compatability we are willing to compromise on if any. +achieve and not break backwards compatibility. Or, what elements of backwards +compatibility we are willing to compromise on if any. ## Interface Rationale Each interface has specific types that satisfy it but not more specialized -interfaces. A selection of non-normative examples. - -- Semigroup: Non-empty arrays/buffers under concatenation (no identity element) -- Monoid: Strings under concatenation (no inverse operation) -- Group: Square matrices under addition (multiplication isn't distributive) -- CommutativeGroup: Vectors under addition (no multiplication) -- Semiring: Boolean algebra (no additive inverses) -- Ring: Square matrices under standard operations (multiplication isn't - commutative) -- CommutativeRing: Dual numbers (no general multiplicative inverse) -- EuclideanRing: Integers (no multiplicative inverse) -- DivisionRing: Quaternions (multiplication isn't commutative) -- Field: Complex numbers, Real numbers (satisfy all field axioms) +interfaces. A selection of non-normative examples: + +- IAdditive: Non-empty arrays/buffers under concatenation (no identity element) +- IAdditiveIdentity: Strings under concatenation (no inverse operation) +- ISubtractable: Square matrices under addition (multiplication isn't + distributive) +- IDistributive: Boolean algebra (no additive inverses) +- IMultiplicative: Square matrices under standard operations (multiplication + isn't commutative) +- ICommutativeRing: Dual numbers (no general multiplicative inverse) +- IRemainder: Integers (no multiplicative inverse) +- IDivisible: Quaternions (multiplication isn't commutative) +- IField: Complex numbers, Real numbers (satisfy all field axioms) ## Floating Point Considerations @@ -198,8 +210,7 @@ Design choices still TBD: - Treatment of unsigned integer literals - Conversion of double precision literals to single precision types - Error reporting mechanisms for out-of-range values -- Whether to provide separate interfaces for different integer types (int32, - uint32, etc.) +- Whether to provide separate interfaces for different integer types (int32, uint32, etc.) ## Generic Programming @@ -207,14 +218,14 @@ This hierarchy enables generic algorithms that work with any type satisfying specific algebraic properties: ```slang -// Generic linear interpolation for any Field -T lerp(T a, T b, T t) +// Generic linear interpolation for any IField +T lerp(T a, T b, T t) { return a * (T.one() - t) + b * t; } -// Generic accumulation for any Monoid -T sum(T[] elements) +// Generic accumulation for any IAdditiveIdentity +T sum(T[] elements) { T result = T.zero(); for(T elem in elements) @@ -223,19 +234,18 @@ T sum(T[] elements) } // Generic matrix multiplication -matrix; mul( +matrix mul( a : matrix, b : matrix ) { - // Implementation using only Ring operations + // Implementation using only IMultiplicative operations } - // Generic geometric transforms -Transform compose(Transform a, Transform b) +Transform compose(Transform a, Transform b) { - // Implementation using Ring operations + // Implementation using IMultiplicative operations } ``` @@ -243,10 +253,9 @@ Transform compose(Transform a, Transform b) ### More nuanced hierarchy -We could go a little further an introduce structures such as a `Magma`, which -could be used to represent non-associative binary operations without an -identity element. This could be used for example for some color mixing, however -this has a major downside in that it defies programmer intuition that the `+` +We could go further and introduce additional interfaces below `IAdditive`, +which could be used for example for some color mixing operations. However, this +has a major downside in that it defies programmer intuition that the `+` operator is associative. ### Operator Overloading Only @@ -267,7 +276,8 @@ will need to built upon some algebraic hierarchy. ### Alternative: Heterogeneous Operation Types -Similar to Rust's approach, we could allow operations to return different types than their inputs: +Similar to Rust's approach, we could allow operations to return different types +than their inputs: ```slang interface Add @@ -296,13 +306,13 @@ extension float : Add This comes with some downsides however: - Non-injective type families (where multiple input type combinations could - produce the same output type) may lead to worse type inference. + produce the same output type) may lead to worse type inference - This flexibility, while powerful, introduces potential confusion about operation semantics - Most mathematical structures in abstract algebra assume operations are closed -- The rare cases where heterogeneous operations are needed can be served - by explicit conversion functions or dedicated methods. This can also be - served by implicit conversions. +- The rare cases where heterogeneous operations are needed can be served by + explicit conversion functions or dedicated methods. This can also be served by + implicit conversions The benefits of simpler type inference and clearer algebraic semantics outweigh the flexibility of heterogeneous operations. @@ -327,7 +337,7 @@ Several potential extensions could enhance this algebraic hierarchy: - Add interfaces for lattices and boolean algebras - Support min/max operations - - Interval arithmetic + - Enable interval arithmetic - Module Interface From ba112662d06e2ce364df834e805a0e8007dc4233 Mon Sep 17 00:00:00 2001 From: Ellie Hermaszewska Date: Wed, 19 Feb 2025 17:13:42 +0800 Subject: [PATCH 4/5] Correct examples --- ...21-abstract-algebra-interface-hierarchy.md | 88 +++++++++++++++---- 1 file changed, 72 insertions(+), 16 deletions(-) diff --git a/proposals/021-abstract-algebra-interface-hierarchy.md b/proposals/021-abstract-algebra-interface-hierarchy.md index ce1dafa..adc4d72 100644 --- a/proposals/021-abstract-algebra-interface-hierarchy.md +++ b/proposals/021-abstract-algebra-interface-hierarchy.md @@ -64,7 +64,7 @@ Implement the following interfaces, replacing in part `__BuiltinArithmeticType`: ```slang // IAdditive represents a semigroup - a set with an associative binary operation // Properties: (a + b) + c = a + (b + c) -// Examples: Non-empty arrays (concatenation), Colors (blending), Positive integers (addition) +// Examples: Non-empty arrays, Finite bounding box intersection, Probability distributions (convolution) interface IAdditive { static This operator+(This a, This b); // Associative addition @@ -72,7 +72,7 @@ interface IAdditive // IAdditiveIdentity represents a monoid - a semigroup with an identity element // Properties: zero() + a = a + zero() = a -// Examples: Arrays (empty array), Natural Numbers (0), Matrices (zero matrix) +// Examples: Arrays/strings under concatenation, Sets under union, Option type interface IAdditiveIdentity : IAdditive { static This zero(); // Additive identity @@ -80,62 +80,60 @@ interface IAdditiveIdentity : IAdditive // ISubtractable represents a group - a monoid with inverse elements // Properties: a + (-a) = (-a) + a = zero() -// Examples: Integers, Real numbers, Vectors, Matrices under addition +// Examples: 2d rotations under composition, permutations under composition interface ISubtractable : IAdditiveIdentity { static This operator-(This t); // Additive inverse static This operator-(This a, This b); }; -// IDistributive combines additive monoid with multiplicative monoid to form a -// semiring. +// IDistributive combines additive monoid with multiplicative monoid to form a semiring. // Properties: Multiplication distributes over addition // (a + b) * c = (a * c) + (b * c) // c * (a + b) = (c * a) + (c * b) // one() * a = a * one() = a -// Examples: Natural numbers, Matrices, Boolean algebra +// Examples: Natural numbers under addition and multiplication, Tropical semiring, Boolean semiring interface IDistributive : IAdditiveIdentity { static This operator*(This a, This b); // Multiplicative operation static This one(); // Multiplicative identity }; -// IMultiplicative combines semiring with additive group to form a ring +// IMultiplicative combines semiring with additive group to form a ring. // Properties: All semiring properties plus additive inverses, multiplication // may not be commutative. -// Examples: Integers, Square matrices, Quaternions +// Examples: Square matrices (non-invertible), Quaternions (non-zero) interface IMultiplicative : IDistributive, ISubtractable { }; -// ICommutativeRing represents a ring where multiplication is commutative +// ICommutativeRing represents a ring where multiplication is commutative. // Properties: a * b = b * a -// Examples: Integers, Real numbers, Complex numbers +// Examples: Polynomials with integer coefficients interface ICommutativeRing : IMultiplicative { // Enforces a * b = b * a }; -// IDivisible adds multiplicative inverses to a IDivible to form a division -// ring +// IDivisible adds multiplicative inverses to a ring to form a division ring. // Properties: x * recip(x) = recip(x) * x = one() -// Examples: Quaternions, Real matrices (when invertible) +// Examples: Quaternions, non-zero reals interface IDivisible : IMultiplicative { static This recip(This x); // Multiplicative inverse static This operator/(This a, This b); // Division }; -// IRemainder adds Euclidean division properties to a commutative ring +// IRemainder adds Euclidean division properties to a commutative ring. // Properties: a = (a / b) * b + (a % b) where norm(a % b) < norm(b) -// Examples: Integers, Polynomials +// Examples: Integers, Gaussian integers interface IRemainder : ICommutativeRing { static This operator%(This a, This b); // Remainder static uint norm(This a); // Absolute value for remainder comparison }; -// IField represents a commutative ring where every non-zero element has a multiplicative inverse +// IField represents a commutative ring where every non-zero element has a multiplicative inverse. // Properties: All commutative ring properties plus multiplicative inverses // Examples: Real numbers, Complex numbers, Rational numbers interface IField : ICommutativeRing, IDivisible @@ -143,6 +141,64 @@ interface IField : ICommutativeRing, IDivisible }; ``` +```mermaid +flowchart TD + IAdditive["IAdditive +(Semigroup) +Examples: Colors, String concat, +Probability distributions"] + + IAdditiveIdentity["IAdditiveIdentity +(Monoid) +Examples: Sets with union, +Functions with pointwise addition"] + + ISubtractable["ISubtractable +(Group) +Examples: Permutations +under composition"] + + IDistributive["IDistributive +(Semiring) +Examples: Natural numbers, +Boolean algebra"] + + IMultiplicative["IMultiplicative +(Ring) +Examples: Square matrices, +Quaternions"] + + ICommutativeRing["ICommutativeRing +(Commutative Ring) +Examples: Polynomials with +integer coefficients"] + + IDivisible["IDivisible +(Division Ring) +Examples: Non-zero +quaternions"] + + IRemainder["IRemainder +(Euclidean Ring) +Examples: Gaussian +integers"] + + IField["IField +(Field) +Examples: Complex numbers, +Rational numbers"] + + IAdditive --> IAdditiveIdentity + IAdditiveIdentity --> ISubtractable + IAdditiveIdentity --> IDistributive + IDistributive & ISubtractable --> IMultiplicative + IMultiplicative --> ICommutativeRing + IMultiplicative --> IDivisible + ICommutativeRing --> IRemainder + ICommutativeRing & IDivisible --> IField + +``` + ## Implementation notes Part of the scope of this work is to determine how close to this design we can From 22d3d0f11a71beb5ecf47f39b138d835e51aaa69 Mon Sep 17 00:00:00 2001 From: Ellie Hermaszewska Date: Wed, 19 Feb 2025 18:16:42 +0800 Subject: [PATCH 5/5] Add diagram and more interfaces --- ...21-abstract-algebra-interface-hierarchy.md | 95 +++++++++++++++---- 1 file changed, 78 insertions(+), 17 deletions(-) diff --git a/proposals/021-abstract-algebra-interface-hierarchy.md b/proposals/021-abstract-algebra-interface-hierarchy.md index adc4d72..e7d284b 100644 --- a/proposals/021-abstract-algebra-interface-hierarchy.md +++ b/proposals/021-abstract-algebra-interface-hierarchy.md @@ -145,47 +145,50 @@ interface IField : ICommutativeRing, IDivisible flowchart TD IAdditive["IAdditive (Semigroup) -Examples: Colors, String concat, -Probability distributions"] +Examples: Non-empty arrays, +Finite bounding box intersection, +Probability distributions (convolution)"] IAdditiveIdentity["IAdditiveIdentity (Monoid) -Examples: Sets with union, -Functions with pointwise addition"] +Examples: Arrays/strings under concatenation, +Sets under union, +Option type"] ISubtractable["ISubtractable (Group) -Examples: Permutations -under composition"] +Examples: 2D rotations under composition, +Permutations under composition"] IDistributive["IDistributive (Semiring) -Examples: Natural numbers, -Boolean algebra"] +Examples: Natural numbers under addition and multiplication, +Tropical semiring, +Boolean semiring"] IMultiplicative["IMultiplicative (Ring) -Examples: Square matrices, -Quaternions"] +Examples: Square matrices (non-invertible), +Quaternions (non-zero)"] ICommutativeRing["ICommutativeRing (Commutative Ring) -Examples: Polynomials with -integer coefficients"] +Examples: Polynomials with integer coefficients"] IDivisible["IDivisible (Division Ring) -Examples: Non-zero -quaternions"] +Examples: Quaternions, +Non-zero reals"] IRemainder["IRemainder (Euclidean Ring) -Examples: Gaussian -integers"] +Examples: Integers, +Gaussian integers"] IField["IField (Field) -Examples: Complex numbers, +Examples: Real numbers, +Complex numbers, Rational numbers"] IAdditive --> IAdditiveIdentity @@ -196,7 +199,65 @@ Rational numbers"] IMultiplicative --> IDivisible ICommutativeRing --> IRemainder ICommutativeRing & IDivisible --> IField +``` + +Additionally the following interfaces extend `IField` to add support for +hyperbolic and trigonometric operations. + +```slang +interface ITrigonometric : IField +{ + static This pi(); + static This sin(This angle); + static This cos(This angle); + static This tan(This angle); + static This asin(This value); + static This acos(This value); + static This atan(This value); + static This atan2(This y, This x); +} + +interface IHyperbolic : IField +{ + static This e(); + static This sinh(This value); + static This cosh(This value); + static This tanh(This value); + static This asinh(This value); + static This acosh(This value); + static This atanh(This value); +} +interface IExponential : IField +{ + static This exp(This x); + static This log(This x); // Natural logarithm, base e + static This log10(This x); // Base-10 logarithm +} +``` + +## Machine values + +```slang +interface IEEE754Float : ITrigonometric, IHyperbolic, IExponential +{ + // IEEE754-specific constants + static This positiveInfinity(); // Returns the IEEE754 +∞ + static This negativeInfinity(); // Returns the IEEE754 -∞ + static This nan(); // Returns a NaN (Not-a-Number) value + static This epsilon(); // Returns the smallest difference such that 1 + epsilon != 1 + + // Classification functions + static bool isNaN(This x); // Returns true if x is NaN + static bool isInfinite(This x); // Returns true if x is positive or negative infinity + static bool isFinite(This x); // Returns true if x is finite (not infinity or NaN) + + // Rounding operations + static This floor(This x); // Returns the largest integer not greater than x + static This ceil(This x); // Returns the smallest integer not less than x + static This round(This x); // Rounds x to the nearest integer + static This trunc(This x); // Truncates x, discarding the fractional part +}; ``` ## Implementation notes