Dear all,
I wrote here some (very high level) considerations about the implementation of "Decimal" (GitHub issue #236).
Please, let me know what do you think about it.
Design
Protocol name and definition
For what concerns the name, I would simply call it Decimal
rather than DecimalFloatingPoint
, It's simpler and shorter. As far as I can see, the only argument that can be made for calling it DecimalFloatingPoint
is symmetry with respect to BinaryFloatingPoint
.
Here I sketched the basic scheme of the Decimal protocol
Besides FloatingPoint
and ExpressibleByFloatLiteral
's properties and methods, I think it would be nice to implement some other useful operations and constants like
@available( ... )
public protocol Decimal: FloatingPoint, ExpressibleByFloatLiteral {
/* Euler's number, approximately equal to 2.71828 */
var e: Self { get }
/* Constant value 0 */
var zero: Self { get }
/* Constant value 1 */
var one: Self { get }
/* returns the integer part of self ÷ other */
func integerDivision(_ other: Self) -> Self
}
Implementation details
The table 3.6 of the IEEE 754-2019 document (p. 23) contains the specifications to implement any decimal floating point number of size k bits, with k being a multiple of 32. For practical reasons, I would stop at 128.
However, it is necessary to decide how the fields containing the information of the floating point number (sign, exponent and mantissa) will be implemented. From my point of view, implementing the structure at a low level (in C) would have the advantage of being able to (spatially) optimize it like that
typedef struct __attribute__((__packed__)) _decimal32 {
unsigned int sign:1;
unsigned int exponent:11;
unsigned int mantissa:20;
} decimal32;
And then write the high level APIs in Swift - keeping in C the structure, the basic operations and the comparisons. The C packed structures would be incredibly useful to implement the Decimal128.
The other option is to write it entirely in Swift as the BinaryFloatingPoint
protocol as the BinaryFloatingPoint
protocol does
public protocol BinaryFloatingPoint: FloatingPoint, ExpressibleByFloatLiteral {
/// A type that represents the encoded significand of a value.
associatedtype RawSignificand: UnsignedInteger
/// A type that represents the encoded exponent of a value.
associatedtype RawExponent: UnsignedInteger
...
}
I don't know whether you try to discourage the use of C within the library itself. For this reason, I leave this decision to be made by those more knowledgeable than me.
Summary
I summarize here some of the key point discussed before:
- Name of the protocol;
- Properties and methods;
- Implementation of the classes: C vs. Swift data structures.
cc @icharleshu