In another post, @scanon outlined some basic requirements before we can define fixed-width Decimal numbers:
There is now a preliminary DecimalFloatingPoint
protocol that could be reviewed by anyone who is interested:
public protocol DecimalFloatingPoint: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
/// Creates a new instance from the specified sign and bit patterns.
///
/// The values passed as `exponentBitPattern` is interpreted in the
/// decimal interchange format defined by the [IEEE 754 specification][spec].
///
/// [spec]: http://ieeexplore.ieee.org/servlet/opac?punumber=4610933
///
/// The `significandBitPattern` are the big-endian, integer decimal digits
/// of the number. For example, the integer number `314` represents a
/// significand of `314`.
///
/// - Parameters:
/// - sign: The sign of the new value.
/// - exponentBitPattern: The bit pattern to use for the exponent field of
/// the new value.
/// - significandBitPattern: Bit pattern to use for the mantissa field of
/// the new value.
init(sign: FloatingPointSign, exponentBitPattern: RawExponent,
significandBitPattern: RawSignificand)
/// Initialize from raw Binary Integer Decimal (BID) or
/// Densely Packed Decimal (DPD) encoded integers.
/// - Parameters:
/// - bits: The bit pattern to use for the new value.
/// - bidEncoding: When `true`, the `bits` are assumed to have a BID
/// encoding; otherwise, a DPD encoding is assumed, which is translated
/// to BID format during initialization.
init(bitPattern bits: RawSignificand, bidEncoding: Bool)
/// Creates a new instance from the given value, rounded to the closest
/// possible representation.
///
/// If two representable values are equally close, the result is the value
/// with more trailing zeros in its significand bit pattern.
///
/// - Parameter value: A floating-point value to be converted.
init<Source:DecimalFloatingPoint>(_ value: Source)
/// Creates a new instance from the given value, if it can be represented
/// exactly.
///
/// If the given floating-point value cannot be represented exactly, the
/// result is `nil`. A value that is NaN ("not a number") cannot be
/// represented exactly if its payload cannot be encoded exactly.
///
/// - Parameter value: A floating-point value to be converted.
init?<Source:DecimalFloatingPoint>(exactly value: Source)
/// A decimal floating-point type's `exponentBias` imposes a limit on the
/// range of the exponent for normal, finite values. The unbiased exponent of
/// a type `F` can be obtained with this attribute. The unbiased exponent
/// can be calculated as:
/// `exponent = exponentBitPattern - exponentBias`
static var exponentBias: Int { get }
/// The number of bits used to represent the type's exponent.
static var exponentBitCount: Int { get }
/// The raw encoding of the value's exponent field.
///
/// This value is unadjusted by the type's exponent bias.
var exponentBitPattern: Self.RawExponent { get }
/// The raw encoding of the value's significand field.
var significandBitPattern: RawSignificand { get }
/// The floating-point value with the same sign and exponent as this value,
/// but with a significand of 1.0.
///
/// A *decade* is a set of decimal floating-point values that all have the
/// same sign and exponent. The `decade` property is a member of the same
/// decade as this value, but with a unit significand.
///
/// In this example, `x` has a value of `21.5`, which is stored as
/// `2.15 * 10**1`, where `**` is exponentiation. Therefore, `x.decade` is
/// equal to `1.0 * 10**1`, or `10.0`.
///```
/// let x = 21.5
/// // x.significand == 2.15
/// // x.exponent == 1
///
/// let y = x.decade
/// // y == 10.0
/// // y.significand == 1.0
/// // y.exponent == 1
///```
var decade: Self { get }
/// True if the internal number encoding is binary integer decimal or BID.
/// The alternative allowed by the IEEE standard is densely packed decimal
/// or DPD.
///
/// The initializer `init(bitPattern:bidEncoding)` works from both DPD and
/// BID. Converters to both formats are also available.
static var isBIDFormat: Bool { get }
// FIXME: - Discussion on how to do rounding and state tracking
/// Class-wide setting for how numbers will be rounded in calculations.
static var rounding: FloatingPointRoundingRule { get set }
/// The number of digits required to represent the value's significand.
///
/// If this value is a finite nonzero number, `significandDigitCount` is the
/// number of decimal digits required to represent the value of
/// `significand`; otherwise, `significandDigitCount` is -1. The value of
/// `significandDigitCount` is always -1 or from one to the
/// `significandMaxDigitCount`. For example:
///
/// - For any representable power of ten, `significandDigitCount` is one,
/// because significand` is `1`.
/// - If `x` is 10, `x.significand` is `10` in decimal, so
/// `x.significandDigitCount` is 2.
/// - If `x` is Decimal32.pi, `x.significand` is `3.141593` in
/// decimal, and `x.significandDigitCount` is 7.
var significandDigitCount: Int { get }
}