# encoding: ascii # api: csharp # title: Saturated arithmetic # description: Saturated addition, subtraction, multiplication, and casting from numeric types to integer types using clamping to handle overflows. # version: 2.1 # type: class # author: Public Domain # license: CC0 # x-poshcode-id: 5415 # x-archived: 2016-05-19T09:39:44 # x-published: 2016-09-09T22:19:00 # # <# Version 2.1: - fixes a couple of typos After loading, use it like (where [T] is a primitive integer type): [sat[T]]::From($a) [sat[T]]::Add($a,$b) [sat[T]]::Sub($a,$b) [sat[T]]::Mul($a,$b) #> Add-Type -ReferencedAssemblies System.Numerics -TypeDefinition @' using System; using System.Numerics; public static class sat where T : struct, IComparable, IEquatable, IConvertible { internal static readonly Func add_; internal static readonly Func sub_; internal static readonly Func mul_; internal static readonly Func i8_; internal static readonly Func u8_; internal static readonly Func i16_; internal static readonly Func u16_; internal static readonly Func i32_; internal static readonly Func u32_; internal static readonly Func i64_; internal static readonly Func u64_; internal static readonly Func f32_; internal static readonly Func f64_; internal static readonly Func m_; internal static readonly Func b_; public static T Add(T a, T b) { return add_(a, b); } public static T Sub(T a, T b) { return sub_(a, b); } public static T Mul(T a, T b) { return mul_(a, b); } public static T From(sbyte value) { return i8_(value); } public static T From(byte value) { return u8_(value); } public static T From(short value) { return i16_(value); } public static T From(ushort value) { return u16_(value); } public static T From(int value) { return i32_(value); } public static T From(uint value) { return u32_(value); } public static T From(long value) { return i64_(value); } public static T From(ulong value) { return u64_(value); } public static T From(float value) { return f32_(value); } public static T From(double value) { return f64_(value); } public static T From(decimal value) { return m_(value); } public static T From(BigInteger value) { return b_(value); } static sat() {unchecked{ add_ = (Func)((sbyte a, sbyte b) => { int ret = a + b; if (ret > sbyte.MaxValue) ret = sbyte.MaxValue; if (ret < sbyte.MinValue) ret = sbyte.MinValue; return (sbyte)ret; }) as Func; if (add_ != null) { sub_ = (Func)((sbyte a, sbyte b) => { int ret = a - b; if (ret > sbyte.MaxValue) ret = sbyte.MaxValue; if (ret < sbyte.MinValue) ret = sbyte.MinValue; return (sbyte)ret; }) as Func; mul_ = (Func)((sbyte a, sbyte b) => { int ret = a * b; if (ret > sbyte.MaxValue) ret = sbyte.MaxValue; if (ret < sbyte.MinValue) ret = sbyte.MinValue; return (sbyte)ret; }) as Func; i8_ = (Func)((sbyte value) => { return value; }) as Func; u8_ = (Func)((byte value) => { return (sbyte)value >= 0 ? (sbyte)value : sbyte.MaxValue; }) as Func; i16_ = (Func)((short value) => { return value <= sbyte.MinValue ? sbyte.MinValue : value <= sbyte.MaxValue ? (sbyte)value : sbyte.MaxValue; }) as Func; u16_ = (Func)((ushort value) => { return value <= sbyte.MaxValue ? (sbyte)value : sbyte.MaxValue; }) as Func; i32_ = (Func)((int value) => { return value <= sbyte.MinValue ? sbyte.MinValue : value <= sbyte.MaxValue ? (sbyte)value : sbyte.MaxValue; }) as Func; u32_ = (Func)((uint value) => { return value <= (byte)sbyte.MaxValue ? (sbyte)value : sbyte.MaxValue; }) as Func; i64_ = (Func)((long value) => { return value <= sbyte.MinValue ? sbyte.MinValue : value <= sbyte.MaxValue ? (sbyte)value : sbyte.MaxValue; }) as Func; u64_ = (Func)((ulong value) => { return value <= (byte)sbyte.MaxValue ? (sbyte)value : sbyte.MaxValue; }) as Func; f32_ = (Func)((float value) => { return value <= sbyte.MinValue ? sbyte.MinValue : value >= sbyte.MaxValue ? sbyte.MaxValue : checked((sbyte)value); }) as Func; f64_ = (Func)((double value) => { return value <= sbyte.MinValue ? sbyte.MinValue : value >= sbyte.MaxValue ? sbyte.MaxValue : checked((sbyte)value); }) as Func; m_ = (Func)((decimal value) => { return value <= sbyte.MinValue ? sbyte.MinValue : value >= sbyte.MaxValue ? sbyte.MaxValue : (sbyte)value; }) as Func; b_ = (Func)((BigInteger value) => { return value <= (long)sbyte.MinValue ? sbyte.MinValue : value >= (long)sbyte.MaxValue ? sbyte.MaxValue : (sbyte)value; }) as Func; return; } add_ = (Func)((byte a, byte b) => { int ret = a + b; if (ret > byte.MaxValue) ret = byte.MaxValue; return (byte)ret; }) as Func; if (add_ != null) { sub_ = (Func)((byte a, byte b) => { int ret = a - b; if (ret < 0) ret = 0; return (byte)ret; }) as Func; mul_ = (Func)((byte a, byte b) => { int ret = a * b; if (ret > byte.MaxValue) ret = byte.MaxValue; return (byte)ret; }) as Func; i8_ = (Func)((sbyte value) => { return value >= 0 ? (byte)value : (byte)0; }) as Func; u8_ = (Func)((byte value) => { return value; }) as Func; i16_ = (Func)((short value) => { return value <= 0 ? (byte)0 : value <= byte.MaxValue ? (byte)value : byte.MaxValue; }) as Func; u16_ = (Func)((ushort value) => { return value <= byte.MaxValue ? (byte)value : byte.MaxValue; }) as Func; i32_ = (Func)((int value) => { return value <= 0 ? (byte)0 : value <= byte.MaxValue ? (byte)value : byte.MaxValue; }) as Func; u32_ = (Func)((uint value) => { return value <= byte.MaxValue ? (byte)value : byte.MaxValue; }) as Func; i64_ = (Func)((long value) => { return value <= 0 ? (byte)0 : value <= byte.MaxValue ? (byte)value : byte.MaxValue; }) as Func; u64_ = (Func)((ulong value) => { return value <= byte.MaxValue ? (byte)value : byte.MaxValue; }) as Func; f32_ = (Func)((float value) => { return value <= 0 ? (byte)0 : value >= byte.MaxValue ? byte.MaxValue : checked((byte)value); }) as Func; f64_ = (Func)((double value) => { return value <= 0 ? (byte)0 : value >= byte.MaxValue ? byte.MaxValue : checked((byte)value); }) as Func; m_ = (Func)((decimal value) => { return value <= 0 ? (byte)0 : value >= byte.MaxValue ? byte.MaxValue : (byte)value; }) as Func; b_ = (Func)((BigInteger value) => { return value.Sign <= 0 ? (byte)0 : value >= (long)byte.MaxValue ? byte.MaxValue : (byte)value; }) as Func; return; } add_ = (Func)((short a, short b) => { int ret = a + b; if (ret > short.MaxValue) ret = short.MaxValue; if (ret < short.MinValue) ret = short.MinValue; return (short)ret; }) as Func; if (add_ != null) { sub_ = (Func)((short a, short b) => { int ret = a - b; if (ret > short.MaxValue) ret = short.MaxValue; if (ret < short.MinValue) ret = short.MinValue; return (short)ret; }) as Func; mul_ = (Func)((short a, short b) => { int ret = a * b; if (ret > short.MaxValue) ret = short.MaxValue; if (ret < short.MinValue) ret = short.MinValue; return (short)ret; }) as Func; i8_ = (Func)((sbyte value) => { return value; }) as Func; u8_ = (Func)((byte value) => { return value; }) as Func; i16_ = (Func)((short value) => { return value; }) as Func; u16_ = (Func)((ushort value) => { return value >= 0 ? (short)value : short.MaxValue; }) as Func; i32_ = (Func)((int value) => { return value <= short.MinValue ? short.MinValue : value <= short.MaxValue ? (short)value : short.MaxValue; }) as Func; u32_ = (Func)((uint value) => { return value <= (ushort)short.MaxValue ? (short)value : short.MaxValue; }) as Func; i64_ = (Func)((long value) => { return value <= short.MinValue ? short.MinValue : value <= short.MaxValue ? (short)value : short.MaxValue; }) as Func; u64_ = (Func)((ulong value) => { return value <= (ushort)short.MaxValue ? (short)value : short.MaxValue; }) as Func; f32_ = (Func)((float value) => { return value <= short.MinValue ? short.MinValue : value >= short.MaxValue ? short.MaxValue : checked((short)value); }) as Func; f64_ = (Func)((double value) => { return value <= short.MinValue ? short.MinValue : value >= short.MaxValue ? short.MaxValue : checked((short)value); }) as Func; m_ = (Func)((decimal value) => { return value <= short.MinValue ? short.MinValue : value >= short.MaxValue ? short.MaxValue : (short)value; }) as Func; b_ = (Func)((BigInteger value) => { return value <= (long)short.MinValue ? short.MinValue : value >= (long)short.MaxValue ? short.MaxValue : (short)value; }) as Func; return; } add_ = (Func)((ushort a, ushort b) => { int ret = a + b; if (ret > ushort.MaxValue) ret = ushort.MaxValue; return (ushort)ret; }) as Func; if (add_ != null) { sub_ = (Func)((ushort a, ushort b) => { int ret = a - b; if (ret < 0) ret = 0; return (ushort)ret; }) as Func; mul_ = (Func)((ushort a, ushort b) => { uint ret = (uint)a * (uint)b; if (ret > ushort.MaxValue) ret = ushort.MaxValue; return (ushort)ret; }) as Func; i8_ = (Func)((sbyte value) => { return value >= 0 ? (ushort)value : (ushort)0; }) as Func; u8_ = (Func)((byte value) => { return value; }) as Func; i16_ = (Func)((short value) => { return value >= 0 ? (ushort)value : (ushort)0; }) as Func; u16_ = (Func)((ushort value) => { return value; }) as Func; i32_ = (Func)((int value) => { return value <= 0 ? (ushort)0 : value <= ushort.MaxValue ? (ushort)value : ushort.MaxValue; }) as Func; u32_ = (Func)((uint value) => { return value <= ushort.MaxValue ? (ushort)value : ushort.MaxValue; }) as Func; i64_ = (Func)((long value) => { return value <= 0 ? (ushort)0 : value <= ushort.MaxValue ? (ushort)value : ushort.MaxValue; }) as Func; u64_ = (Func)((ulong value) => { return value <= ushort.MaxValue ? (ushort)value : ushort.MaxValue; }) as Func; f32_ = (Func)((float value) => { return value <= 0 ? (ushort)0 : value >= ushort.MaxValue ? ushort.MaxValue : checked((ushort)value); }) as Func; f64_ = (Func)((double value) => { return value <= 0 ? (ushort)0 : value >= ushort.MaxValue ? ushort.MaxValue : checked((ushort)value); }) as Func; m_ = (Func)((decimal value) => { return value <= 0 ? (ushort)0 : value >= ushort.MaxValue ? ushort.MaxValue : (ushort)value; }) as Func; b_ = (Func)((BigInteger value) => { return value.Sign <= 0 ? (ushort)0 : value >= (long)ushort.MaxValue ? ushort.MaxValue : (ushort)value; }) as Func; return; } add_ = (Func)((int a, int b) => { long ret = (long)a + (long)b; if (ret > int.MaxValue) ret = int.MaxValue; if (ret < int.MinValue) ret = int.MinValue; return (int)ret; }) as Func; if (add_ != null) { sub_ = (Func)((int a, int b) => { long ret = (long)a - (long)b; if (ret > int.MaxValue) ret = int.MaxValue; if (ret < int.MinValue) ret = int.MinValue; return (int)ret; }) as Func; mul_ = (Func)((int a, int b) => { long ret = (long)a * (long)b; if (ret > int.MaxValue) ret = int.MaxValue; if (ret < int.MinValue) ret = int.MinValue; return (int)ret; }) as Func; i8_ = (Func)((sbyte value) => { return value; }) as Func; u8_ = (Func)((byte value) => { return value; }) as Func; i16_ = (Func)((short value) => { return value; }) as Func; u16_ = (Func)((ushort value) => { return value; }) as Func; i32_ = (Func)((int value) => { return value; }) as Func; u32_ = (Func)((uint value) => { return (int)value >= 0 ? (int)value : int.MaxValue; }) as Func; i64_ = (Func)((long value) => { return value <= int.MinValue ? int.MinValue : value <= int.MaxValue ? (int)value : int.MaxValue; }) as Func; u64_ = (Func)((ulong value) => { return value <= (uint)int.MaxValue ? (int)value : int.MaxValue; }) as Func; f32_ = (Func)((float value) => { return value <= int.MinValue ? int.MinValue : value >= -(float)int.MinValue ? int.MaxValue : checked((int)value); }) as Func; f64_ = (Func)((double value) => { return value <= int.MinValue ? int.MinValue : value >= int.MaxValue ? int.MaxValue : checked((int)value); }) as Func; m_ = (Func)((decimal value) => { return value <= int.MinValue ? int.MinValue : value >= int.MaxValue ? int.MaxValue : (int)value; }) as Func; b_ = (Func)((BigInteger value) => { return value <= (long)int.MinValue ? int.MinValue : value >= (long)int.MaxValue ? int.MaxValue : (int)value; }) as Func; return; } add_ = (Func)((uint a, uint b) => { ulong ret = (ulong)a + (ulong)b; if (ret > uint.MaxValue) ret = uint.MaxValue; return (uint)ret; }) as Func; if (add_ != null) { sub_ = (Func)((uint a, uint b) => { long ret = (long)a - (long)b; if (ret < 0) ret = 0; return (uint)ret; }) as Func; mul_ = (Func)((uint a, uint b) => { ulong ret = (ulong)a * (ulong)b; if (ret > uint.MaxValue) ret = uint.MaxValue; return (uint)ret; }) as Func; i8_ = (Func)((sbyte value) => { return value >= 0 ? (byte)value : 0U; }) as Func; u8_ = (Func)((byte value) => { return value; }) as Func; i16_ = (Func)((short value) => { return value >= 0 ? (ushort)value : 0U; }) as Func; u16_ = (Func)((ushort value) => { return value; }) as Func; i32_ = (Func)((int value) => { return value >= 0 ? (uint)value : 0U; }) as Func; u32_ = (Func)((uint value) => { return value; }) as Func; i64_ = (Func)((long value) => { return value <= 0 ? 0U : value <= uint.MaxValue ? (uint)value : uint.MaxValue; }) as Func; u64_ = (Func)((ulong value) => { return value <= uint.MaxValue ? (uint)value : uint.MaxValue; }) as Func; f32_ = (Func)((float value) => { return value <= 0 ? 0U : value >= 4294967296.0f ? uint.MaxValue : checked((uint)value); }) as Func; f64_ = (Func)((double value) => { return value <= 0 ? 0U : value >= uint.MaxValue ? uint.MaxValue : checked((uint)value); }) as Func; m_ = (Func)((decimal value) => { return value <= 0 ? 0U : value >= uint.MaxValue ? uint.MaxValue : (uint)value; }) as Func; b_ = (Func)((BigInteger value) => { return value.Sign <= 0 ? 0U : value >= (long)uint.MaxValue ? uint.MaxValue : (uint)value; }) as Func; return; } add_ = (Func)((long a, long b) => { long ret = a + b; long ov = (ret < 0) ? long.MaxValue : long.MinValue; if (((a ^ ret) & (b ^ ret)) < 0) ret = ov; return ret; }) as Func; if (add_ != null) { sub_ = (Func)((long a, long b) => { long ret = a - b; long ov = (ret < 0) ? long.MaxValue : long.MinValue; if (((a ^ b) & (a ^ ret)) < 0) ret = ov; return ret; }) as Func; mul_ = (Func)((long a, long b) => { if (a > 0) { if (b >= 0) return b <= long.MaxValue / a ? a*b : long.MaxValue; return b >= long.MinValue / a ? a*b : long.MinValue; } else if (a < 0) { if (b <= 0) return b >= long.MaxValue / a ? a*b : long.MaxValue; return a >= long.MinValue / b ? a*b : long.MinValue; } return 0; }) as Func; i8_ = (Func)((sbyte value) => { return value; }) as Func; u8_ = (Func)((byte value) => { return value; }) as Func; i16_ = (Func)((short value) => { return value; }) as Func; u16_ = (Func)((ushort value) => { return value; }) as Func; i32_ = (Func)((int value) => { return value; }) as Func; u32_ = (Func)((uint value) => { return value; }) as Func; i64_ = (Func)((long value) => { return value; }) as Func; u64_ = (Func)((ulong value) => { return (long)value >= 0 ? (long)value : long.MaxValue; }) as Func; f32_ = (Func)((float value) => { return value <= long.MinValue ? long.MinValue : value >= -(float)long.MinValue ? long.MaxValue : checked((long)value); }) as Func; f64_ = (Func)((double value) => { return value <= long.MinValue ? long.MinValue : value >= -(double)long.MinValue ? long.MaxValue : checked((long)value); }) as Func; m_ = (Func)((decimal value) => { return value >= long.MaxValue ? long.MaxValue : value <= long.MinValue ? long.MinValue : (long)value; }) as Func; b_ = (Func)((BigInteger value) => { return value >= long.MaxValue ? long.MaxValue : value <= long.MinValue ? long.MinValue : (long)value; }) as Func; return; } add_ = (Func)((ulong a, ulong b) => { return a + b >= a ? a + b : ulong.MaxValue; }) as Func; if (add_ != null) { sub_ = (Func)((ulong a, ulong b) => { return a - b <= a ? a - b : 0UL; }) as Func; mul_ = (Func)((ulong a, ulong b) => { if (b == 0) return 0UL; return a <= ulong.MaxValue / b ? a*b : ulong.MaxValue; }) as Func; i8_ = (Func)((sbyte value) => { return value >= 0 ? (byte)value : 0UL; }) as Func; u8_ = (Func)((byte value) => { return value; }) as Func; i16_ = (Func)((short value) => { return value >= 0 ? (ushort)value : 0UL; }) as Func; u16_ = (Func)((ushort value) => { return value; }) as Func; i32_ = (Func)((int value) => { return value >= 0 ? (uint)value : 0UL; }) as Func; u32_ = (Func)((uint value) => { return value; }) as Func; i64_ = (Func)((long value) => { return value >= 0 ? (ulong)value : 0UL; }) as Func; u64_ = (Func)((ulong value) => { return value; }) as Func; f32_ = (Func)((float value) => { return value <= 0 ? 0UL : value >= 18446744073709551616.0f ? ulong.MaxValue : checked((ulong)value); }) as Func; f64_ = (Func)((double value) => { return value <= 0 ? 0UL : value >= 18446744073709551616.0 ? ulong.MaxValue : checked((ulong)value); }) as Func; m_ = (Func)((decimal value) => { return value <= 0 ? 0UL : value >= ulong.MaxValue ? ulong.MaxValue : (ulong)value; }) as Func; b_ = (Func)((BigInteger value) => { return value.Sign <= 0 ? 0UL : value >= ulong.MaxValue ? ulong.MaxValue : (ulong)value; }) as Func; return; } throw new SystemException(); }} } '@