Skip to content

Instantly share code, notes, and snippets.

@xwu
Last active January 18, 2017 05:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xwu/a4250536ff8e5d207682079b641e9408 to your computer and use it in GitHub Desktop.
Save xwu/a4250536ff8e5d207682079b641e9408 to your computer and use it in GitHub Desktop.
Numeric Protocols

Arithmetic

protocol Arithmetic : Equatable, ExpressibleByIntegerLiteral

An type that provides certain arithmetic operations (addition, subtraction, and multiplication).

Types that conform to Arithmetic satisfy the following conditions for any values a, b, and c (unless the result of an operation overflows the maximum size of the conforming type):

  • Addition (+) is commutative; that is, a + b == b + a

  • Addition is associative; that is, (a + b) + c == a + (b + c)

  • There is an additive identity expressible by 0 such that a + 0 == a

  • Subtraction (-) is the inverse of addition; that is, (a + b) - b == a, and subtraction of a value from itself gives the additive identity

  • Multiplication (*) may or may not be commutative but is associative

  • There is an multiplicative identity expressible by 1 such that a * 1 == a and 1 * a == a

  • Multiplication is distributive over addition (and subtraction); that is, a * (b + c) == (a * b) + (a * c) and (b + c) * a == (b * a) + (c * a)

Because integer division and floating-point division have differing semantics, no such operation is required for conformance to Arithmetic.

SHOULD WE REQUIRE MULTIPLICATION TO BE COMMUTATIVE?
- ARGUMENT FOR NO: allows for anti-commutative multiplication in conforming types.
- ARGUMENT FOR YES: almost anyone who's writing a generic algorithm,
  unless well-versed in math and/or reading the fine print, will assume it is.

SignedArithmetic

protocol SignedArithmetic : Arithmetic

An arithmetic type that can be negated.

Types that conform to SignedArithmetic satisfy the following condition for any non-zero value a:

  • Negation (using the unary operator -) gives an additive inverse -a such that 0 - a == -a (unless the result of evaluating 0 - a overflows the maximum size of the conforming type, in which case the result of evaluating -a also overflows)
SHOULD `signum` BE DEFINED HERE INSTEAD?
[Edit: No, it can't be, since SignedArithmetic does not refine Comparable.]

(Integer protocols)

BinaryInteger refines Arithmetic and Comparable. It provides the following semantics (sketched briefly):

  • Multiplication is commutative [if not already guaranteed by Arithmetic]; that is a * b == b * a

  • Division (/) has the semantics of integer division

  • Modulo (%) has the semantics of integer modulo, with the result having the same sign as the dividend

DOES `BinaryInteger` NEED TO HAVE A STATIC PROPERTY `isSigned`?
Types should conform to either SignedInteger or UnsignedInteger.

FixedWidthInteger refines BinaryInteger; SignedInteger refines BinaryInteger and SignedArithmetic; and UnsignedInteger refines BinaryInteger only.

(Floating point protocols)

FloatingPoint refines SignedArithmetic. It provides the following semantics (sketched briefly).

  • Multiplication is commutative [if not already guaranteed by Arithmetic]; that is a * b == b * a

  • Division (/) is the inverse of multiplication; 1 / a gives the multiplicative inverse of a

BinaryFloatingPoint refines FloatingPoint.

@dabrahams
Copy link

This is very helpful; thanks for writing it up.

@xwu
Copy link
Author

xwu commented Jan 17, 2017

@dabrahams Re-written for clarity and accuracy; I think the major remaining semantic question is Steve's questioning whether Arithmetic should guarantee that a * b == b * a.

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