Commit 89d71a960b

Marc Tiehuis <marctiehuis@gmail.com>
2019-05-01 08:15:57
std.math: Add documentation for all functions and algorithm sources
1 parent f94964c
std/math/big/int.zig
@@ -21,32 +21,49 @@ comptime {
     debug.assert(Limb.is_signed == false);
 }
 
+/// An arbitrary-precision big integer.
+///
+/// Memory is allocated by an Int as needed to ensure operations never overflow. The range of an
+/// Int is bounded only by available memory.
 pub const Int = struct {
     const sign_bit: usize = 1 << (usize.bit_count - 1);
 
+    /// Default number of limbs to allocate on creation of an Int.
+    pub const default_capacity = 4;
+
+    /// Allocator used by the Int when requesting memory.
     allocator: ?*Allocator,
-    //  - little-endian ordered
-    //  - len >= 1 always
-    //  - zero value -> len == 1 with limbs[0] == 0
+
+    /// Raw digits. These are:
+    ///
+    /// * Little-endian ordered
+    /// * limbs.len >= 1
+    /// * Zero is represent as Int.len() == 1 with limbs[0] == 0.
+    ///
+    /// Accessing limbs directly should be avoided.
     limbs: []Limb,
-    // High bit is the sign bit. 1 is negative, 0 positive.
-    // Remaining bits indicate the number of used limbs.
-    //
-    // If Zig gets smarter about packing data, this can be rewritten as a u1 and usize - 1 field.
-    metadata: usize,
 
-    const default_capacity = 4;
+    /// High bit is the sign bit. If set, Int is negative, else Int is positive.
+    /// The remaining bits represent the number of limbs used by Int.
+    metadata: usize,
 
+    /// Creates a new Int. default_capacity limbs will be allocated immediately.
+    /// Int will be zeroed.
     pub fn init(allocator: *Allocator) !Int {
         return try Int.initCapacity(allocator, default_capacity);
     }
 
+    /// Creates a new Int. Int will be set to `value`.
+    ///
+    /// This is identical to an `init`, followed by a `set`.
     pub fn initSet(allocator: *Allocator, value: var) !Int {
         var s = try Int.init(allocator);
         try s.set(value);
         return s;
     }
 
+    /// Creates a new Int with a specific capacity. If capacity < default_capacity then the
+    /// default capacity will be used instead.
     pub fn initCapacity(allocator: *Allocator, capacity: usize) !Int {
         return Int{
             .allocator = allocator,
@@ -59,14 +76,17 @@ pub const Int = struct {
         };
     }
 
+    /// Returns the number of limbs currently in use.
     pub fn len(self: Int) usize {
         return self.metadata & ~sign_bit;
     }
 
+    /// Returns whether an Int is positive.
     pub fn isPositive(self: Int) bool {
         return self.metadata & sign_bit == 0;
     }
 
+    /// Sets the sign of an Int.
     pub fn setSign(self: *Int, positive: bool) void {
         if (positive) {
             self.metadata &= ~sign_bit;
@@ -75,14 +95,17 @@ pub const Int = struct {
         }
     }
 
+    /// Sets the length of an Int.
+    ///
+    /// If setLen is used, then the Int must be normalized to suit.
     pub fn setLen(self: *Int, new_len: usize) void {
         self.metadata &= sign_bit;
         self.metadata |= new_len;
     }
 
-    // Initialize an Int directly from a fixed set of limb values. This is considered read-only
-    // and cannot be used as a receiver argument to any functions. If this tries to allocate
-    // at any point a panic will occur due to the null allocator.
+    /// Returns an Int backed by a fixed set of limb values.
+    /// This is read-only and cannot be used as a result argument. If the Int tries to allocate
+    /// memory a runtime panic will occur.
     pub fn initFixed(limbs: []const Limb) Int {
         var self = Int{
             .allocator = null,
@@ -95,6 +118,9 @@ pub const Int = struct {
         return self;
     }
 
+    /// Ensures an Int has enough space allocated for capacity limbs. If the Int does not have
+    /// sufficient capacity, the exact amount will be allocated. This occurs even if the requested
+    /// capacity is only greater than the current capacity by one limb.
     pub fn ensureCapacity(self: *Int, capacity: usize) !void {
         self.assertWritable();
         if (capacity <= self.limbs.len) {
@@ -110,12 +136,15 @@ pub const Int = struct {
         }
     }
 
+    /// Frees all memory associated with an Int.
     pub fn deinit(self: *Int) void {
         self.assertWritable();
         self.allocator.?.free(self.limbs);
         self.* = undefined;
     }
 
+    /// Clones an Int and returns a new Int with the same value. The new Int is a deep copy and
+    /// can be modified separately from the original.
     pub fn clone(other: Int) !Int {
         other.assertWritable();
         return Int{
@@ -129,6 +158,8 @@ pub const Int = struct {
         };
     }
 
+    /// Copies the value of an Int to an existing Int so that they both have the same value.
+    /// Extra memory will be allocated if the receiver does not have enough capacity.
     pub fn copy(self: *Int, other: Int) !void {
         self.assertWritable();
         if (self.limbs.ptr == other.limbs.ptr) {
@@ -140,6 +171,8 @@ pub const Int = struct {
         self.metadata = other.metadata;
     }
 
+    /// Efficiently swap an Int with another. This swaps the limb pointers and a full copy is not
+    /// performed. The address of the limbs field will not be the same after this function.
     pub fn swap(self: *Int, other: *Int) void {
         self.assertWritable();
         mem.swap(Int, self, other);
@@ -152,35 +185,39 @@ pub const Int = struct {
         debug.warn("\n");
     }
 
+    /// Negate the sign of an Int.
     pub fn negate(self: *Int) void {
         self.metadata ^= sign_bit;
     }
 
+    /// Make an Int positive.
     pub fn abs(self: *Int) void {
         self.metadata &= ~sign_bit;
     }
 
+    /// Returns true if an Int is odd.
     pub fn isOdd(self: Int) bool {
         return self.limbs[0] & 1 != 0;
     }
 
+    /// Returns true if an Int is even.
     pub fn isEven(self: Int) bool {
         return !self.isOdd();
     }
 
-    // Returns the number of bits required to represent the absolute value of self.
+    /// Returns the number of bits required to represent the absolute value an Int.
     fn bitCountAbs(self: Int) usize {
         return (self.len() - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len() - 1]));
     }
 
-    // Returns the number of bits required to represent the integer in twos-complement form.
-    //
-    // If the integer is negative the value returned is the number of bits needed by a signed
-    // integer to represent the value. If positive the value is the number of bits for an
-    // unsigned integer. Any unsigned integer will fit in the signed integer with bitcount
-    // one greater than the returned value.
-    //
-    // e.g. -127 returns 8 as it will fit in an i8. 127 returns 7 since it fits in a u7.
+    /// Returns the number of bits required to represent the integer in twos-complement form.
+    ///
+    /// If the integer is negative the value returned is the number of bits needed by a signed
+    /// integer to represent the value. If positive the value is the number of bits for an
+    /// unsigned integer. Any unsigned integer will fit in the signed integer with bitcount
+    /// one greater than the returned value.
+    ///
+    /// e.g. -127 returns 8 as it will fit in an i8. 127 returns 7 since it fits in a u7.
     fn bitCountTwosComp(self: Int) usize {
         var bits = self.bitCountAbs();
 
@@ -203,7 +240,7 @@ pub const Int = struct {
         return bits;
     }
 
-    pub fn fitsInTwosComp(self: Int, is_signed: bool, bit_count: usize) bool {
+    fn fitsInTwosComp(self: Int, is_signed: bool, bit_count: usize) bool {
         if (self.eqZero()) {
             return true;
         }
@@ -215,18 +252,20 @@ pub const Int = struct {
         return bit_count >= req_bits;
     }
 
+    /// Returns whether self can fit into an integer of the requested type.
     pub fn fits(self: Int, comptime T: type) bool {
         return self.fitsInTwosComp(T.is_signed, T.bit_count);
     }
 
-    // Returns the approximate size of the integer in the given base. Negative values accommodate for
-    // the minus sign. This is used for determining the number of characters needed to print the
-    // value. It is inexact and will exceed the given value by 1-2 digits.
+    /// Returns the approximate size of the integer in the given base. Negative values accommodate for
+    /// the minus sign. This is used for determining the number of characters needed to print the
+    /// value. It is inexact and may exceed the given value by ~1-2 bytes.
     pub fn sizeInBase(self: Int, base: usize) usize {
         const bit_count = usize(@boolToInt(!self.isPositive())) + self.bitCountAbs();
         return (bit_count / math.log2(base)) + 1;
     }
 
+    /// Sets an Int to value. Value must be an primitive integer type.
     pub fn set(self: *Int, value: var) Allocator.Error!void {
         self.assertWritable();
         const T = @typeOf(value);
@@ -290,6 +329,9 @@ pub const Int = struct {
         TargetTooSmall,
     };
 
+    /// Convert self to type T.
+    ///
+    /// Returns an error if self cannot be narrowed into the requested type without truncation.
     pub fn to(self: Int, comptime T: type) ConvertError!T {
         switch (@typeId(T)) {
             TypeId.Int => {
@@ -353,6 +395,13 @@ pub const Int = struct {
         };
     }
 
+    /// Set self from the string representation `value`.
+    ///
+    /// value must contain only digits <= `base`. Base prefixes are not allowed (e.g. 0x43 should
+    /// simply be 43).
+    ///
+    /// Returns an error if memory could not be allocated or `value` has invalid digits for the
+    /// requested base.
     pub fn setString(self: *Int, base: u8, value: []const u8) !void {
         self.assertWritable();
         if (base < 2 or base > 16) {
@@ -380,6 +429,8 @@ pub const Int = struct {
         self.setSign(positive);
     }
 
+    /// Converts self to a string in the requested base. Memory is allocated from the provided
+    /// allocator and not the one present in self.
     /// TODO make this call format instead of the other way around
     pub fn toString(self: Int, allocator: *Allocator, base: u8) ![]const u8 {
         if (base < 2 or base > 16) {
@@ -463,7 +514,7 @@ pub const Int = struct {
         return s;
     }
 
-    /// for the std lib format function
+    /// To allow `std.fmt.printf` to work with Int.
     /// TODO make this non-allocating
     pub fn format(
         self: Int,
@@ -480,7 +531,7 @@ pub const Int = struct {
         return output(context, str);
     }
 
-    // returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
+    /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
     pub fn cmpAbs(a: Int, b: Int) i8 {
         if (a.len() < b.len()) {
             return -1;
@@ -505,7 +556,7 @@ pub const Int = struct {
         }
     }
 
-    // returns -1, 0, 1 if a < b, a == b or a > b respectively.
+    /// Returns -1, 0, 1 if a < b, a == b or a > b respectively.
     pub fn cmp(a: Int, b: Int) i8 {
         if (a.isPositive() != b.isPositive()) {
             return if (a.isPositive()) i8(1) else -1;
@@ -515,17 +566,17 @@ pub const Int = struct {
         }
     }
 
-    // if a == 0
+    /// Returns true if a == 0.
     pub fn eqZero(a: Int) bool {
         return a.len() == 1 and a.limbs[0] == 0;
     }
 
-    // if |a| == |b|
+    /// Returns true if |a| == |b|.
     pub fn eqAbs(a: Int, b: Int) bool {
         return cmpAbs(a, b) == 0;
     }
 
-    // if a == b
+    /// Returns true if a == b.
     pub fn eq(a: Int, b: Int) bool {
         return cmp(a, b) == 0;
     }
@@ -559,7 +610,11 @@ pub const Int = struct {
         };
     }
 
-    // r = a + b
+    /// r = a + b
+    ///
+    /// r, a and b may be aliases.
+    ///
+    /// Returns an error if memory could not be allocated.
     pub fn add(r: *Int, a: Int, b: Int) Allocator.Error!void {
         r.assertWritable();
         if (a.eqZero()) {
@@ -617,7 +672,11 @@ pub const Int = struct {
         r[i] = carry;
     }
 
-    // r = a - b
+    /// r = a - b
+    ///
+    /// r, a and b may be aliases.
+    ///
+    /// Returns an error if memory could not be allocated.
     pub fn sub(r: *Int, a: Int, b: Int) !void {
         r.assertWritable();
         if (a.isPositive() != b.isPositive()) {
@@ -684,9 +743,11 @@ pub const Int = struct {
         debug.assert(borrow == 0);
     }
 
-    // rma = a * b
-    //
-    // For greatest efficiency, ensure rma does not alias a or b.
+    /// rma = a * b
+    ///
+    /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
+    ///
+    /// Returns an error if memory could not be allocated.
     pub fn mul(rma: *Int, a: Int, b: Int) !void {
         rma.assertWritable();
 
@@ -759,6 +820,9 @@ pub const Int = struct {
         }
     }
 
+    /// q = a / b (rem r)
+    ///
+    /// a / b are floored (rounded towards 0).
     pub fn divFloor(q: *Int, r: *Int, a: Int, b: Int) !void {
         try div(q, r, a, b);
 
@@ -771,6 +835,9 @@ pub const Int = struct {
         r.setSign(b.isPositive());
     }
 
+    /// q = a / b (rem r)
+    ///
+    /// a / b are truncated (rounded towards -inf).
     pub fn divTrunc(q: *Int, r: *Int, a: Int, b: Int) !void {
         try div(q, r, a, b);
         r.setSign(a.isPositive());
@@ -969,7 +1036,7 @@ pub const Int = struct {
         r.normalize(r.len());
     }
 
-    // r = a << shift, in other words, r = a * 2^shift
+    /// r = a << shift, in other words, r = a * 2^shift
     pub fn shiftLeft(r: *Int, a: Int, shift: usize) !void {
         r.assertWritable();
 
@@ -1002,7 +1069,7 @@ pub const Int = struct {
         mem.set(Limb, r[0 .. limb_shift - 1], 0);
     }
 
-    // r = a >> shift
+    /// r = a >> shift
     pub fn shiftRight(r: *Int, a: Int, shift: usize) !void {
         r.assertWritable();
 
@@ -1038,7 +1105,9 @@ pub const Int = struct {
         }
     }
 
-    // r = a | b
+    /// r = a | b
+    ///
+    /// a and b are zero-extended to the longer of a or b.
     pub fn bitOr(r: *Int, a: Int, b: Int) !void {
         r.assertWritable();
 
@@ -1067,7 +1136,7 @@ pub const Int = struct {
         }
     }
 
-    // r = a & b
+    /// r = a & b
     pub fn bitAnd(r: *Int, a: Int, b: Int) !void {
         r.assertWritable();
 
@@ -1093,7 +1162,7 @@ pub const Int = struct {
         }
     }
 
-    // r = a ^ b
+    /// r = a ^ b
     pub fn bitXor(r: *Int, a: Int, b: Int) !void {
         r.assertWritable();
 
@@ -1279,10 +1348,8 @@ test "big.int bitcount/to" {
     try a.set(0);
     testing.expect(a.bitCountTwosComp() == 0);
 
-    // TODO: stack smashing
-    // testing.expect((try a.to(u0)) == 0);
-    // TODO: sigsegv
-    // testing.expect((try a.to(i0)) == 0);
+    testing.expect((try a.to(u0)) == 0);
+    testing.expect((try a.to(i0)) == 0);
 
     try a.set(-1);
     testing.expect(a.bitCountTwosComp() == 1);
std/math/big/rational.zig
@@ -14,11 +14,22 @@ const Limb = bn.Limb;
 const DoubleLimb = bn.DoubleLimb;
 const Int = bn.Int;
 
+/// An arbitrary-precision rational number.
+///
+/// Memory is allocated as needed for operations to ensure full precision is kept. The precision
+/// of a Rational is only bounded by memory.
+///
+/// Rational's are always normalized. That is, for a Rational r = p/q where p and q are integers,
+/// gcd(p, q) = 1 always.
 pub const Rational = struct {
-    // Sign of Rational is sign of p. Sign of q is ignored
+    /// Numerator. Determines the sign of the Rational.
     p: Int,
+
+    /// Denominator. Sign is ignored.
     q: Int,
 
+    /// Create a new Rational. A small amount of memory will be allocated on initialization.
+    /// This will be 2 * Int.default_capacity.
     pub fn init(a: *Allocator) !Rational {
         return Rational{
             .p = try Int.init(a),
@@ -26,18 +37,21 @@ pub const Rational = struct {
         };
     }
 
+    /// Frees all memory associated with a Rational.
     pub fn deinit(self: *Rational) void {
         self.p.deinit();
         self.q.deinit();
     }
 
+    /// Set a Rational from a primitive integer type.
     pub fn setInt(self: *Rational, a: var) !void {
         try self.p.set(a);
         try self.q.set(1);
     }
 
-    // TODO: Accept a/b fractions and exponent form
+    /// Set a Rational from a string of the form `A/B` where A and B are base-10 integers.
     pub fn setFloatString(self: *Rational, str: []const u8) !void {
+        // TODO: Accept a/b fractions and exponent form
         if (str.len == 0) {
             return error.InvalidFloatString;
         }
@@ -111,8 +125,10 @@ pub const Rational = struct {
         }
     }
 
-    // Translated from golang.go/src/math/big/rat.go.
+    /// Set a Rational from a floating-point value. The rational will have enough precision to
+    /// completely represent the provided float.
     pub fn setFloat(self: *Rational, comptime T: type, f: T) !void {
+        // Translated from golang.go/src/math/big/rat.go.
         debug.assert(@typeId(T) == builtin.TypeId.Float);
 
         const UnsignedIntType = @IntType(false, T.bit_count);
@@ -164,8 +180,13 @@ pub const Rational = struct {
         try self.reduce();
     }
 
-    // Translated from golang.go/src/math/big/rat.go.
+    /// Return a floating-point value that is the closest value to a Rational.
+    ///
+    /// The result may not be exact if the Rational is too precise or too large for the
+    /// target type.
     pub fn toFloat(self: Rational, comptime T: type) !T {
+        // Translated from golang.go/src/math/big/rat.go.
+        // TODO: Indicate whether the result is not exact.
         debug.assert(@typeId(T) == builtin.TypeId.Float);
 
         const fsize = T.bit_count;
@@ -259,6 +280,7 @@ pub const Rational = struct {
         return if (self.p.isPositive()) f else -f;
     }
 
+    /// Set a rational from an integer ratio.
     pub fn setRatio(self: *Rational, p: var, q: var) !void {
         try self.p.set(p);
         try self.q.set(q);
@@ -273,11 +295,13 @@ pub const Rational = struct {
         }
     }
 
+    /// Set a Rational directly from an Int.
     pub fn copyInt(self: *Rational, a: Int) !void {
         try self.p.copy(a);
         try self.q.set(1);
     }
 
+    /// Set a Rational directly from a ratio of two Int's.
     pub fn copyRatio(self: *Rational, a: Int, b: Int) !void {
         try self.p.copy(a);
         try self.q.copy(b);
@@ -288,23 +312,29 @@ pub const Rational = struct {
         try self.reduce();
     }
 
+    /// Make a Rational positive.
     pub fn abs(r: *Rational) void {
         r.p.abs();
     }
 
+    /// Negate the sign of a Rational.
     pub fn negate(r: *Rational) void {
         r.p.negate();
     }
 
+    /// Efficiently swap a Rational with another. This swaps the limb pointers and a full copy is not
+    /// performed. The address of the limbs field will not be the same after this function.
     pub fn swap(r: *Rational, other: *Rational) void {
         r.p.swap(&other.p);
         r.q.swap(&other.q);
     }
 
+    /// Returns -1, 0, 1 if a < b, a == b or a > b respectively.
     pub fn cmp(a: Rational, b: Rational) !i8 {
         return cmpInternal(a, b, true);
     }
 
+    /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.
     pub fn cmpAbs(a: Rational, b: Rational) !i8 {
         return cmpInternal(a, b, false);
     }
@@ -325,9 +355,11 @@ pub const Rational = struct {
         return if (is_abs) q.cmpAbs(p) else q.cmp(p);
     }
 
-    // r/q = ap/aq + bp/bq = (ap*bq + bp*aq) / (aq*bq)
-    //
-    // For best performance, rma should not alias a or b.
+    /// rma = a + b.
+    ///
+    /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
+    ///
+    /// Returns an error if memory could not be allocated.
     pub fn add(rma: *Rational, a: Rational, b: Rational) !void {
         var r = rma;
         var aliased = rma.p.limbs.ptr == a.p.limbs.ptr or rma.p.limbs.ptr == b.p.limbs.ptr;
@@ -351,9 +383,11 @@ pub const Rational = struct {
         try r.reduce();
     }
 
-    // r/q = ap/aq - bp/bq = (ap*bq - bp*aq) / (aq*bq)
-    //
-    // For best performance, rma should not alias a or b.
+    /// rma = a - b.
+    ///
+    /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
+    ///
+    /// Returns an error if memory could not be allocated.
     pub fn sub(rma: *Rational, a: Rational, b: Rational) !void {
         var r = rma;
         var aliased = rma.p.limbs.ptr == a.p.limbs.ptr or rma.p.limbs.ptr == b.p.limbs.ptr;
@@ -377,14 +411,22 @@ pub const Rational = struct {
         try r.reduce();
     }
 
-    // r/q = ap/aq * bp/bq = ap*bp / aq*bq
+    /// rma = a * b.
+    ///
+    /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
+    ///
+    /// Returns an error if memory could not be allocated.
     pub fn mul(r: *Rational, a: Rational, b: Rational) !void {
         try r.p.mul(a.p, b.p);
         try r.q.mul(a.q, b.q);
         try r.reduce();
     }
 
-    // r/q = (ap/aq) / (bp/bq) = ap*bq / bp*aq
+    /// rma = a / b.
+    ///
+    /// rma, a and b may be aliases. However, it is more efficient if rma does not alias a or b.
+    ///
+    /// Returns an error if memory could not be allocated.
     pub fn div(r: *Rational, a: Rational, b: Rational) !void {
         if (b.p.eqZero()) {
             @panic("division by zero");
@@ -395,7 +437,7 @@ pub const Rational = struct {
         try r.reduce();
     }
 
-    // r/q = q/r
+    /// Invert the numerator and denominator fields of a Rational. p/q => q/p.
     pub fn invert(r: *Rational) void {
         Int.swap(&r.p, &r.q);
     }
std/math/complex/abs.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the absolute value (modulus) of z.
 pub fn abs(z: var) @typeOf(z.re) {
     const T = @typeOf(z.re);
     return math.hypot(T, z.re, z.im);
std/math/complex/acos.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the arc-cosine of z.
 pub fn acos(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
     const q = cmath.asin(z);
std/math/complex/acosh.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the hyperbolic arc-cosine of z.
 pub fn acosh(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
     const q = cmath.acos(z);
std/math/complex/arg.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the angular component (in radians) of z.
 pub fn arg(z: var) @typeOf(z.re) {
     const T = @typeOf(z.re);
     return math.atan2(T, z.im, z.re);
std/math/complex/asin.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+// Returns the arc-sine of z.
 pub fn asin(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
     const x = z.re;
std/math/complex/asinh.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the hyperbolic arc-sine of z.
 pub fn asinh(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
     const q = Complex(T).new(-z.im, z.re);
std/math/complex/atan.zig
@@ -1,9 +1,16 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/catanf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/catan.c
+
 const std = @import("../../std.zig");
 const testing = std.testing;
 const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the arc-tangent of z.
 pub fn atan(z: var) @typeOf(z) {
     const T = @typeOf(z.re);
     return switch (T) {
std/math/complex/atanh.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the hyperbolic arc-tangent of z.
 pub fn atanh(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
     const q = Complex(T).new(-z.im, z.re);
std/math/complex/conj.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the complex conjugate of z.
 pub fn conj(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
     return Complex(T).new(z.re, -z.im);
std/math/complex/cos.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the cosine of z.
 pub fn cos(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
     const p = Complex(T).new(-z.im, z.re);
std/math/complex/cosh.zig
@@ -1,3 +1,9 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/ccoshf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/ccosh.c
+
 const std = @import("../../std.zig");
 const testing = std.testing;
 const math = std.math;
@@ -6,6 +12,7 @@ const Complex = cmath.Complex;
 
 const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;
 
+/// Returns the hyperbolic arc-cosine of z.
 pub fn cosh(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
     return switch (T) {
std/math/complex/exp.zig
@@ -1,3 +1,9 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/cexpf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/cexp.c
+
 const std = @import("../../std.zig");
 const testing = std.testing;
 const math = std.math;
@@ -6,6 +12,7 @@ const Complex = cmath.Complex;
 
 const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;
 
+/// Returns e raised to the power of z (e^z).
 pub fn exp(z: var) @typeOf(z) {
     const T = @typeOf(z.re);
 
std/math/complex/ldexp.zig
@@ -1,9 +1,16 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/__cexpf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/__cexp.c
+
 const std = @import("../../std.zig");
 const debug = std.debug;
 const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns exp(z) scaled to avoid overflow.
 pub fn ldexp_cexp(z: var, expt: i32) @typeOf(z) {
     const T = @typeOf(z.re);
 
std/math/complex/log.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the natural logarithm of z.
 pub fn log(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
     const r = cmath.abs(z);
std/math/complex/pow.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns z raised to the complex power of c.
 pub fn pow(comptime T: type, z: T, c: T) T {
     const p = cmath.log(z);
     const q = c.mul(p);
std/math/complex/proj.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the projection of z onto the riemann sphere.
 pub fn proj(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
 
std/math/complex/sin.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the sine of z.
 pub fn sin(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
     const p = Complex(T).new(-z.im, z.re);
std/math/complex/sinh.zig
@@ -1,3 +1,9 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/csinhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/csinh.c
+
 const std = @import("../../std.zig");
 const testing = std.testing;
 const math = std.math;
@@ -6,6 +12,7 @@ const Complex = cmath.Complex;
 
 const ldexp_cexp = @import("ldexp.zig").ldexp_cexp;
 
+/// Returns the hyperbolic sine of z.
 pub fn sinh(z: var) @typeOf(z) {
     const T = @typeOf(z.re);
     return switch (T) {
std/math/complex/sqrt.zig
@@ -1,9 +1,17 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/csqrtf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/csqrt.c
+
 const std = @import("../../std.zig");
 const testing = std.testing;
 const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the square root of z. The real and imaginary parts of the result have the same sign
+/// as the imaginary part of z.
 pub fn sqrt(z: var) @typeOf(z) {
     const T = @typeOf(z.re);
 
std/math/complex/tan.zig
@@ -4,6 +4,7 @@ const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the tanget of z.
 pub fn tan(z: var) Complex(@typeOf(z.re)) {
     const T = @typeOf(z.re);
     const q = Complex(T).new(-z.im, z.re);
std/math/complex/tanh.zig
@@ -1,9 +1,16 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/ctanhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/complex/ctanh.c
+
 const std = @import("../../std.zig");
 const testing = std.testing;
 const math = std.math;
 const cmath = math.complex;
 const Complex = cmath.Complex;
 
+/// Returns the hyperbolic tangent of z.
 pub fn tanh(z: var) @typeOf(z) {
     const T = @typeOf(z.re);
     return switch (T) {
std/math/acos.zig
@@ -1,11 +1,17 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - acos(x)   = nan if x < -1 or x > 1
+// https://git.musl-libc.org/cgit/musl/tree/src/math/acosf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/acos.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns the arc-cosine of x.
+///
+/// Special cases:
+///  - acos(x)   = nan if x < -1 or x > 1
 pub fn acos(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/acosh.zig
@@ -1,13 +1,19 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - acosh(x)   = snan if x < 1
-// - acosh(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/acoshf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/acosh.c
 
 const builtin = @import("builtin");
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns the hyperbolic arc-cosine of x.
+///
+/// Special cases:
+///  - acosh(x)   = snan if x < 1
+///  - acosh(nan) = nan
 pub fn acosh(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/asin.zig
@@ -1,12 +1,18 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - asin(+-0) = +-0
-// - asin(x)   = nan if x < -1 or x > 1
+// https://git.musl-libc.org/cgit/musl/tree/src/math/asinf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/asin.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns the arc-sin of x.
+///
+/// Special Cases:
+///  - asin(+-0) = +-0
+///  - asin(x)   = nan if x < -1 or x > 1
 pub fn asin(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/asinh.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - asinh(+-0)   = +-0
-// - asinh(+-inf) = +-inf
-// - asinh(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/asinhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/asinh.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 
+/// Returns the hyperbolic arc-sin of x.
+///
+/// Special Cases:
+///  - asinh(+-0)   = +-0
+///  - asinh(+-inf) = +-inf
+///  - asinh(nan)   = nan
 pub fn asinh(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/atan.zig
@@ -1,12 +1,18 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - atan(+-0)   = +-0
-// - atan(+-inf) = +-pi/2
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atanf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atan.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns the arc-tangent of x.
+///
+/// Special Cases:
+///  - atan(+-0)   = +-0
+///  - atan(+-inf) = +-pi/2
 pub fn atan(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/atan2.zig
@@ -1,27 +1,33 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-//  atan2(y, nan)     = nan
-//  atan2(nan, x)     = nan
-//  atan2(+0, x>=0)   = +0
-//  atan2(-0, x>=0)   = -0
-//  atan2(+0, x<=-0)  = +pi
-//  atan2(-0, x<=-0)  = -pi
-//  atan2(y>0, 0)     = +pi/2
-//  atan2(y<0, 0)     = -pi/2
-//  atan2(+inf, +inf) = +pi/4
-//  atan2(-inf, +inf) = -pi/4
-//  atan2(+inf, -inf) = 3pi/4
-//  atan2(-inf, -inf) = -3pi/4
-//  atan2(y, +inf)    = 0
-//  atan2(y>0, -inf)  = +pi
-//  atan2(y<0, -inf)  = -pi
-//  atan2(+inf, x)    = +pi/2
-//  atan2(-inf, x)    = -pi/2
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atan2f.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atan2.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns the arc-tangent of y/x.
+///
+/// Special Cases:
+///  - atan2(y, nan)     = nan
+///  - atan2(nan, x)     = nan
+///  - atan2(+0, x>=0)   = +0
+///  - atan2(-0, x>=0)   = -0
+///  - atan2(+0, x<=-0)  = +pi
+///  - atan2(-0, x<=-0)  = -pi
+///  - atan2(y>0, 0)     = +pi/2
+///  - atan2(y<0, 0)     = -pi/2
+///  - atan2(+inf, +inf) = +pi/4
+///  - atan2(-inf, +inf) = -pi/4
+///  - atan2(+inf, -inf) = 3pi/4
+///  - atan2(-inf, -inf) = -3pi/4
+///  - atan2(y, +inf)    = 0
+///  - atan2(y>0, -inf)  = +pi
+///  - atan2(y<0, -inf)  = -pi
+///  - atan2(+inf, x)    = +pi/2
+///  - atan2(-inf, x)    = -pi/2
 pub fn atan2(comptime T: type, y: T, x: T) T {
     return switch (T) {
         f32 => atan2_32(y, x),
std/math/atanh.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - atanh(+-1) = +-inf with signal
-// - atanh(x)   = nan if |x| > 1 with signal
-// - atanh(nan) = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atanhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/atanh.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 
+/// Returns the hyperbolic arc-tangent of x.
+///
+/// Special Cases:
+///  - atanh(+-1) = +-inf with signal
+///  - atanh(x)   = nan if |x| > 1 with signal
+///  - atanh(nan) = nan
 pub fn atanh(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/cbrt.zig
@@ -1,13 +1,19 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - cbrt(+-0)   = +-0
-// - cbrt(+-inf) = +-inf
-// - cbrt(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/cbrtf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/cbrt.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns the cube root of x.
+///
+/// Special Cases:
+///  - cbrt(+-0)   = +-0
+///  - cbrt(+-inf) = +-inf
+///  - cbrt(nan)   = nan
 pub fn cbrt(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/ceil.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - ceil(+-0)   = +-0
-// - ceil(+-inf) = +-inf
-// - ceil(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/ceilf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/ceil.c
 
 const builtin = @import("builtin");
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns the least integer value greater than of equal to x.
+///
+/// Special Cases:
+///  - ceil(+-0)   = +-0
+///  - ceil(+-inf) = +-inf
+///  - ceil(nan)   = nan
 pub fn ceil(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/complex.zig
@@ -23,13 +23,18 @@ pub const sqrt = @import("complex/sqrt.zig").sqrt;
 pub const tanh = @import("complex/tanh.zig").tanh;
 pub const tan = @import("complex/tan.zig").tan;
 
+/// A complex number consisting of a real an imaginary part. T must be a floating-point value.
 pub fn Complex(comptime T: type) type {
     return struct {
         const Self = @This();
 
+        /// Real part.
         re: T,
+
+        /// Imaginary part.
         im: T,
 
+        /// Create a new Complex number from the given real and imaginary parts.
         pub fn new(re: T, im: T) Self {
             return Self{
                 .re = re,
@@ -37,6 +42,7 @@ pub fn Complex(comptime T: type) type {
             };
         }
 
+        /// Returns the sum of two complex numbers.
         pub fn add(self: Self, other: Self) Self {
             return Self{
                 .re = self.re + other.re,
@@ -44,6 +50,7 @@ pub fn Complex(comptime T: type) type {
             };
         }
 
+        /// Returns the subtraction of two complex numbers.
         pub fn sub(self: Self, other: Self) Self {
             return Self{
                 .re = self.re - other.re,
@@ -51,6 +58,7 @@ pub fn Complex(comptime T: type) type {
             };
         }
 
+        /// Returns the product of two complex numbers.
         pub fn mul(self: Self, other: Self) Self {
             return Self{
                 .re = self.re * other.re - self.im * other.im,
@@ -58,6 +66,7 @@ pub fn Complex(comptime T: type) type {
             };
         }
 
+        /// Returns the quotient of two complex numbers.
         pub fn div(self: Self, other: Self) Self {
             const re_num = self.re * other.re + self.im * other.im;
             const im_num = self.im * other.re - self.re * other.im;
@@ -69,6 +78,7 @@ pub fn Complex(comptime T: type) type {
             };
         }
 
+        /// Returns the complex conjugate of a number.
         pub fn conjugate(self: Self) Self {
             return Self{
                 .re = self.re,
@@ -76,6 +86,7 @@ pub fn Complex(comptime T: type) type {
             };
         }
 
+        /// Returns the reciprocal of a complex number.
         pub fn reciprocal(self: Self) Self {
             const m = self.re * self.re + self.im * self.im;
             return Self{
@@ -84,6 +95,7 @@ pub fn Complex(comptime T: type) type {
             };
         }
 
+        /// Returns the magnitude of a complex number.
         pub fn magnitude(self: Self) T {
             return math.sqrt(self.re * self.re + self.im * self.im);
         }
std/math/copysign.zig
@@ -1,8 +1,15 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/math/copysignf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/copysign.c
+
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 
+/// Returns a value with the magnitude of x and the sign of y.
 pub fn copysign(comptime T: type, x: T, y: T) T {
     return switch (T) {
         f16 => copysign16(x, y),
std/math/cosh.zig
@@ -1,8 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - cosh(+-0)   = 1
-// - cosh(+-inf) = +inf
-// - cosh(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/coshf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/cosh.c
 
 const builtin = @import("builtin");
 const std = @import("../std.zig");
@@ -11,6 +11,12 @@ const expo2 = @import("expo2.zig").expo2;
 const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 
+/// Returns the hyperbolic cosine of x.
+///
+/// Special Cases:
+///  - cosh(+-0)   = 1
+///  - cosh(+-inf) = +inf
+///  - cosh(nan)   = nan
 pub fn cosh(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/exp.zig
@@ -1,13 +1,19 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - exp(+inf) = +inf
-// - exp(nan)  = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/expf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/exp.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const assert = std.debug.assert;
 const builtin = @import("builtin");
 
+/// Returns e raised to the power of x (e^x).
+///
+/// Special Cases:
+///  - exp(+inf) = +inf
+///  - exp(nan)  = nan
 pub fn exp(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/exp2.zig
@@ -1,12 +1,18 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - exp2(+inf) = +inf
-// - exp2(nan)  = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/exp2f.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/exp2.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns 2 raised to the power of x (2^x).
+///
+/// Special Cases:
+///  - exp2(+inf) = +inf
+///  - exp2(nan)  = nan
 pub fn exp2(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/expm1.zig
@@ -1,14 +1,23 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - expm1(+inf) = +inf
-// - expm1(-inf) = -1
-// - expm1(nan)  = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/expmf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/expm.c
+
+// TODO: Updated recently.
 
 const builtin = @import("builtin");
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns e raised to the power of x, minus 1 (e^x - 1). This is more accurate than exp(e, x) - 1
+/// when x is near 0.
+///
+/// Special Cases:
+///  - expm1(+inf) = +inf
+///  - expm1(-inf) = -1
+///  - expm1(nan)  = nan
 pub fn expm1(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/expo2.zig
@@ -1,5 +1,12 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/math/__expo2f.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/__expo2.c
+
 const math = @import("../math.zig");
 
+/// Returns exp(x) / 2 for x >= log(maxFloat(T)).
 pub fn expo2(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/fabs.zig
@@ -1,13 +1,19 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - fabs(+-inf) = +inf
-// - fabs(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/fabsf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/fabs.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 
+/// Returns the absolute value of x.
+///
+/// Special Cases:
+///  - fabs(+-inf) = +inf
+///  - fabs(nan)   = nan
 pub fn fabs(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/floor.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - floor(+-0)   = +-0
-// - floor(+-inf) = +-inf
-// - floor(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/floorf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/floor.c
 
 const builtin = @import("builtin");
 const expect = std.testing.expect;
 const std = @import("../std.zig");
 const math = std.math;
 
+/// Returns the greatest integer value less than or equal to x.
+///
+/// Special Cases:
+///  - floor(+-0)   = +-0
+///  - floor(+-inf) = +-inf
+///  - floor(nan)   = nan
 pub fn floor(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/frexp.zig
@@ -1,8 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - frexp(+-0)   = +-0, 0
-// - frexp(+-inf) = +-inf, 0
-// - frexp(nan)   = nan, undefined
+// https://git.musl-libc.org/cgit/musl/tree/src/math/frexpf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/frexp.c
 
 const std = @import("../std.zig");
 const math = std.math;
@@ -17,6 +17,13 @@ fn frexp_result(comptime T: type) type {
 pub const frexp32_result = frexp_result(f32);
 pub const frexp64_result = frexp_result(f64);
 
+/// Breaks x into a normalized fraction and an integral power of two.
+/// f == frac * 2^exp, with |frac| in the interval [0.5, 1).
+///
+/// Special Cases:
+///  - frexp(+-0)   = +-0, 0
+///  - frexp(+-inf) = +-inf, 0
+///  - frexp(nan)   = nan, undefined
 pub fn frexp(x: var) frexp_result(@typeOf(x)) {
     const T = @typeOf(x);
     return switch (T) {
std/math/hypot.zig
@@ -1,15 +1,21 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - hypot(+-inf, y)  = +inf
-// - hypot(x, +-inf)  = +inf
-// - hypot(nan, y)    = nan
-// - hypot(x, nan)    = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/hypotf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/hypot.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 
+/// Returns sqrt(x * x + y * y), avoiding unncessary overflow and underflow.
+///
+/// Special Cases:
+///  - hypot(+-inf, y)  = +inf
+///  - hypot(x, +-inf)  = +inf
+///  - hypot(nan, y)    = nan
+///  - hypot(x, nan)    = nan
 pub fn hypot(comptime T: type, x: T, y: T) T {
     return switch (T) {
         f32 => hypot32(x, y),
std/math/ilogb.zig
@@ -1,8 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - ilogb(+-inf) = maxInt(i32)
-// - ilogb(0)     = maxInt(i32)
-// - ilogb(nan)   = maxInt(i32)
+// https://git.musl-libc.org/cgit/musl/tree/src/math/ilogbf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/ilogb.c
 
 const std = @import("../std.zig");
 const math = std.math;
@@ -10,6 +10,12 @@ const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 const minInt = std.math.minInt;
 
+/// Returns the binary exponent of x as an integer.
+///
+/// Special Cases:
+///  - ilogb(+-inf) = maxInt(i32)
+///  - ilogb(0)     = maxInt(i32)
+///  - ilogb(nan)   = maxInt(i32)
 pub fn ilogb(x: var) i32 {
     const T = @typeOf(x);
     return switch (T) {
std/math/inf.zig
@@ -1,6 +1,7 @@
 const std = @import("../std.zig");
 const math = std.math;
 
+/// Returns value inf for the type T.
 pub fn inf(comptime T: type) T {
     return switch (T) {
         f16 => math.inf_f16,
std/math/isfinite.zig
@@ -3,6 +3,7 @@ const math = std.math;
 const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 
+/// Returns whether x is a finite value.
 pub fn isFinite(x: var) bool {
     const T = @typeOf(x);
     switch (T) {
std/math/isinf.zig
@@ -3,6 +3,7 @@ const math = std.math;
 const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 
+/// Returns whether x is an infinity, ignoring sign.
 pub fn isInf(x: var) bool {
     const T = @typeOf(x);
     switch (T) {
@@ -28,6 +29,7 @@ pub fn isInf(x: var) bool {
     }
 }
 
+/// Returns whether x is an infinity with a positive sign.
 pub fn isPositiveInf(x: var) bool {
     const T = @typeOf(x);
     switch (T) {
@@ -49,6 +51,7 @@ pub fn isPositiveInf(x: var) bool {
     }
 }
 
+/// Returns whether x is an infinity with a negative sign.
 pub fn isNegativeInf(x: var) bool {
     const T = @typeOf(x);
     switch (T) {
std/math/isnan.zig
@@ -3,13 +3,15 @@ const math = std.math;
 const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 
+/// Returns whether x is a nan.
 pub fn isNan(x: var) bool {
     return x != x;
 }
 
-/// Note: A signalling nan is identical to a standard nan right now but may have a different bit
-/// representation in the future when required.
+/// Returns whether x is a signalling nan.
 pub fn isSignalNan(x: var) bool {
+    // Note: A signalling nan is identical to a standard nan right now but may have a different bit
+    // representation in the future when required.
     return isNan(x);
 }
 
std/math/isnormal.zig
@@ -3,6 +3,7 @@ const math = std.math;
 const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 
+// Returns whether x has a normalized representation (i.e. integer part of mantissa is 1).
 pub fn isNormal(x: var) bool {
     const T = @typeOf(x);
     switch (T) {
std/math/ln.zig
@@ -1,9 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - ln(+inf)  = +inf
-// - ln(0)     = -inf
-// - ln(x)     = nan if x < 0
-// - ln(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/lnf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/ln.c
 
 const std = @import("../std.zig");
 const math = std.math;
@@ -11,6 +10,13 @@ const expect = std.testing.expect;
 const builtin = @import("builtin");
 const TypeId = builtin.TypeId;
 
+/// Returns the natural logarithm of x.
+///
+/// Special Cases:
+///  - ln(+inf)  = +inf
+///  - ln(0)     = -inf
+///  - ln(x)     = nan if x < 0
+///  - ln(nan)   = nan
 pub fn ln(x: var) @typeOf(x) {
     const T = @typeOf(x);
     switch (@typeId(T)) {
std/math/log.zig
@@ -1,9 +1,16 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/math/logf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log.c
+
 const std = @import("../std.zig");
 const math = std.math;
 const builtin = @import("builtin");
 const TypeId = builtin.TypeId;
 const expect = std.testing.expect;
 
+/// Returns the logarithm of x for the provided base.
 pub fn log(comptime T: type, base: T, x: T) T {
     if (base == 2) {
         return math.log2(x);
std/math/log10.zig
@@ -1,9 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - log10(+inf)  = +inf
-// - log10(0)     = -inf
-// - log10(x)     = nan if x < 0
-// - log10(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log10f.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log10.c
 
 const std = @import("../std.zig");
 const math = std.math;
@@ -12,6 +11,13 @@ const builtin = @import("builtin");
 const TypeId = builtin.TypeId;
 const maxInt = std.math.maxInt;
 
+/// Returns the base-10 logarithm of x.
+///
+/// Special Cases:
+///  - log10(+inf)  = +inf
+///  - log10(0)     = -inf
+///  - log10(x)     = nan if x < 0
+///  - log10(nan)   = nan
 pub fn log10(x: var) @typeOf(x) {
     const T = @typeOf(x);
     switch (@typeId(T)) {
std/math/log1p.zig
@@ -1,16 +1,22 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - log1p(+inf)  = +inf
-// - log1p(+-0)   = +-0
-// - log1p(-1)    = -inf
-// - log1p(x)     = nan if x < -1
-// - log1p(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log1pf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log1p.c
 
 const builtin = @import("builtin");
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns the natural logarithm of 1 + x with greater accuracy when x is near zero.
+///
+/// Special Cases:
+///  - log1p(+inf)  = +inf
+///  - log1p(+-0)   = +-0
+///  - log1p(-1)    = -inf
+///  - log1p(x)     = nan if x < -1
+///  - log1p(nan)   = nan
 pub fn log1p(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/log2.zig
@@ -1,9 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - log2(+inf)  = +inf
-// - log2(0)     = -inf
-// - log2(x)     = nan if x < 0
-// - log2(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log2f.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/log2.c
 
 const std = @import("../std.zig");
 const math = std.math;
@@ -12,6 +11,13 @@ const builtin = @import("builtin");
 const TypeId = builtin.TypeId;
 const maxInt = std.math.maxInt;
 
+/// Returns the base-2 logarithm of x.
+///
+/// Special Cases:
+///  - log2(+inf)  = +inf
+///  - log2(0)     = -inf
+///  - log2(x)     = nan if x < 0
+///  - log2(nan)   = nan
 pub fn log2(x: var) @typeOf(x) {
     const T = @typeOf(x);
     switch (@typeId(T)) {
std/math/modf.zig
@@ -1,7 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - modf(+-inf) = +-inf, nan
-// - modf(nan)   = nan, nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/modff.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/modf.c
 
 const std = @import("../std.zig");
 const math = std.math;
@@ -17,6 +18,12 @@ fn modf_result(comptime T: type) type {
 pub const modf32_result = modf_result(f32);
 pub const modf64_result = modf_result(f64);
 
+/// Returns the integer and fractional floating-point numbers that sum to x. The sign of each
+/// result is the same as the sign of x.
+///
+/// Special Cases:
+///  - modf(+-inf) = +-inf, nan
+///  - modf(nan)   = nan, nan
 pub fn modf(x: var) modf_result(@typeOf(x)) {
     const T = @typeOf(x);
     return switch (T) {
std/math/nan.zig
@@ -1,5 +1,6 @@
 const math = @import("../math.zig");
 
+/// Returns the nan representation for type T.
 pub fn nan(comptime T: type) T {
     return switch (T) {
         f16 => math.nan_f16,
@@ -10,9 +11,10 @@ pub fn nan(comptime T: type) T {
     };
 }
 
-// Note: A signalling nan is identical to a standard right now by may have a different bit
-// representation in the future when required.
+/// Returns the signalling nan representation for type T.
 pub fn snan(comptime T: type) T {
+    // Note: A signalling nan is identical to a standard right now by may have a different bit
+    // representation in the future when required.
     return switch (T) {
         f16 => @bitCast(f16, math.nan_u16),
         f32 => @bitCast(f32, math.nan_u32),
std/math/powi.zig
@@ -1,12 +1,7 @@
-// Special Cases:
+// Based on Rust, which is licensed under the MIT license.
+// https://github.com/rust-lang/rust/blob/360432f1e8794de58cd94f34c9c17ad65871e5b5/LICENSE-MIT
 //
-//  powi(x, +-0)   = 1 for any x
-//  powi(0, y)     = 0 for any y
-//  powi(1, y)     = 1 for any y
-//  powi(-1, y)    = -1 for for y an odd integer
-//  powi(-1, y)    = 1 for for y an even integer
-//  powi(x, y)     = Overflow for for y >= @sizeOf(x) - 1 y > 0
-//  powi(x, y)     = Underflow for for y > @sizeOf(x) - 1 y < 0
+// https://github.com/rust-lang/rust/blob/360432f1e8794de58cd94f34c9c17ad65871e5b5/src/libcore/num/mod.rs#L3423
 
 const builtin = @import("builtin");
 const std = @import("../std.zig");
@@ -14,7 +9,16 @@ const math = std.math;
 const assert = std.debug.assert;
 const testing = std.testing;
 
-// This implementation is based on that from the rust stlib
+/// Returns the power of x raised by the integer y (x^y).
+///
+/// Special Cases:
+///  - powi(x, +-0)   = 1 for any x
+///  - powi(0, y)     = 0 for any y
+///  - powi(1, y)     = 1 for any y
+///  - powi(-1, y)    = -1 for y an odd integer
+///  - powi(-1, y)    = 1 for y an even integer
+///  - powi(x, y)     = Overflow for y >= @sizeOf(x) - 1 or y > 0
+///  - powi(x, y)     = Underflow for y > @sizeOf(x) - 1 or y < 0
 pub fn powi(comptime T: type, x: T, y: T) (error{
     Overflow,
     Underflow,
std/math/round.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - round(+-0)   = +-0
-// - round(+-inf) = +-inf
-// - round(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/roundf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/round.c
 
 const builtin = @import("builtin");
 const expect = std.testing.expect;
 const std = @import("../std.zig");
 const math = std.math;
 
+/// Returns x rounded to the nearest integer, rounding half away from zero.
+///
+/// Special Cases:
+///  - round(+-0)   = +-0
+///  - round(+-inf) = +-inf
+///  - round(nan)   = nan
 pub fn round(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/scalbn.zig
@@ -1,7 +1,14 @@
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
+//
+// https://git.musl-libc.org/cgit/musl/tree/src/math/scalbnf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/scalbn.c
+
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns x * 2^n.
 pub fn scalbn(x: var, n: i32) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/signbit.zig
@@ -2,6 +2,7 @@ const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 
+/// Returns whether x is negative or negative 0.
 pub fn signbit(x: var) bool {
     const T = @typeOf(x);
     return switch (T) {
std/math/sinh.zig
@@ -1,8 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - sinh(+-0)   = +-0
-// - sinh(+-inf) = +-inf
-// - sinh(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/sinhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/sinh.c
 
 const builtin = @import("builtin");
 const std = @import("../std.zig");
@@ -11,6 +11,12 @@ const expect = std.testing.expect;
 const expo2 = @import("expo2.zig").expo2;
 const maxInt = std.math.maxInt;
 
+/// Returns the hyperbolic sine of x.
+///
+/// Special Cases:
+///  - sinh(+-0)   = +-0
+///  - sinh(+-inf) = +-inf
+///  - sinh(nan)   = nan
 pub fn sinh(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/sqrt.zig
@@ -1,10 +1,3 @@
-// Special Cases:
-//
-// - sqrt(+inf)  = +inf
-// - sqrt(+-0)   = +-0
-// - sqrt(x)     = nan if x < 0
-// - sqrt(nan)   = nan
-
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
@@ -12,6 +5,13 @@ const builtin = @import("builtin");
 const TypeId = builtin.TypeId;
 const maxInt = std.math.maxInt;
 
+/// Returns the square root of x.
+///
+/// Special Cases:
+///  - sqrt(+inf)  = +inf
+///  - sqrt(+-0)   = +-0
+///  - sqrt(x)     = nan if x < 0
+///  - sqrt(nan)   = nan
 pub fn sqrt(x: var) (if (@typeId(@typeOf(x)) == TypeId.Int) @IntType(false, @typeOf(x).bit_count / 2) else @typeOf(x)) {
     const T = @typeOf(x);
     switch (@typeId(T)) {
std/math/tanh.zig
@@ -1,8 +1,8 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - sinh(+-0)   = +-0
-// - sinh(+-inf) = +-1
-// - sinh(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/tanhf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/tanh.c
 
 const builtin = @import("builtin");
 const std = @import("../std.zig");
@@ -11,6 +11,12 @@ const expect = std.testing.expect;
 const expo2 = @import("expo2.zig").expo2;
 const maxInt = std.math.maxInt;
 
+/// Returns the hyperbolic tangent of x.
+///
+/// Special Cases:
+///  - sinh(+-0)   = +-0
+///  - sinh(+-inf) = +-1
+///  - sinh(nan)   = nan
 pub fn tanh(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {
std/math/trunc.zig
@@ -1,14 +1,20 @@
-// Special Cases:
+// Ported from musl, which is licensed under the MIT license:
+// https://git.musl-libc.org/cgit/musl/tree/COPYRIGHT
 //
-// - trunc(+-0)   = +-0
-// - trunc(+-inf) = +-inf
-// - trunc(nan)   = nan
+// https://git.musl-libc.org/cgit/musl/tree/src/math/truncf.c
+// https://git.musl-libc.org/cgit/musl/tree/src/math/trunc.c
 
 const std = @import("../std.zig");
 const math = std.math;
 const expect = std.testing.expect;
 const maxInt = std.math.maxInt;
 
+/// Returns the integer value of x.
+///
+/// Special Cases:
+///  - trunc(+-0)   = +-0
+///  - trunc(+-inf) = +-inf
+///  - trunc(nan)   = nan
 pub fn trunc(x: var) @typeOf(x) {
     const T = @typeOf(x);
     return switch (T) {