checkedint ~master (2017-04-21T23:53:16Z)

- assertsmodule checkedint.asserts
Aliases for the

`checkedint`module using`IntFlagPolicy.asserts`.- flagsmodule checkedint.flags
Common error signaling facilities for the

`checkedint`package.- stickymodule checkedint.sticky
Aliases for the

`checkedint`module using`IntFlagPolicy.sticky`.- testsmodule checkedint.tests
Test the correctness and performance of the

`checkedint`package.- throwsmodule checkedint.throws
Aliases for the

`checkedint`module using`IntFlagPolicy.throws`.- traitsmodule checkedint.traits
Templates to facilitate treating

`checkedint.SmartInt`and`checkedint.SafeInt`like the built-in numeric types in generic code.

- safeInt
`SafeInt!(N, policy, bitOps)`safeInt`(N num)` Get the value of

`num`as a`SafeInt!N`. The integral type`N`can be infered from the argument.- smartInt
`SmartInt!(N, policy, bitOps)`smartInt`(N num)` Get the value of

`num`as a`SmartInt!N`. The integral type`N`can be infered from the argument.

- bits
`inout(N)`bits [@property getter] `inout(N)`bits [@property getter]`N`bits [@property getter]`SmartInt!(BasicScalar!N, N.policy, Yes.bitOps)`bits [@property getter]`SafeInt!(BasicScalar!N, N.policy, Yes.bitOps)`bits [@property getter]Get a view or copy of

`num`that supports bitwise operations.- bscal
`inout(N)`bscal [@property getter] `inout(N)`bscal [@property getter]`N`bscal [@property getter]`BasicScalar!N`bscal [@property getter]Get a view or copy of

`num`as a basic scalar.- idx
`Select!(isSigned!N, ptrdiff_t, size_t)`idx [@property getter] `Select!(isSigned!(BasicScalar!N), ptrdiff_t, size_t)`idx [@property getter]Cast

`num`to a basic type suitable for indexing an array.

- SafeIntstruct SafeInt(N, IntFlagPolicy _policy, Flag!"bitOps" bitOps = Yes.bitOps)
Wrapper for any basic integral type

`N`that uses the checked operations from`safeOp`and rejects attempts to directly assign values that cannot be proven to be within the range representable by`N`. (`checkedint.to()`can be used to safely assign values of incompatible types, with runtime bounds checking.)- SmartIntstruct SmartInt(N, IntFlagPolicy _policy, Flag!"bitOps" bitOps = Yes.bitOps)
Wrapper for any basic integral type

`N`that uses the checked operations from`smartOp`and bounds checks assignments with`checkedint.to()`.

- BasicScalartemplate BasicScalar(T)
Aliases to the basic scalar type associated with

`T`, assuming either:`isScalarType!T`, or`isCheckedInt!T`

Otherwise,

`BasicScalar`aliases to`void`.- DebugInttemplate DebugInt(N, IntFlagPolicy policy, Flag!"bitOps" bitOps = Yes.bitOps)
`template``alias`that evaluates to`SafeInt!(N, policy, bitOps)`in debug mode, and`N`in release mode. This way,`SafeInt!N`is used to debug integer logic while testing, but the basic`N`is used in release mode for maximum speed and the smallest binaries.- SafeInttemplate SafeInt(N, IntFlagPolicy policy, Flag!"bitOps" bitOps = Yes.bitOps)
Wrapper for any basic integral type

`N`that uses the checked operations from`safeOp`and rejects attempts to directly assign values that cannot be proven to be within the range representable by`N`. (`checkedint.to()`can be used to safely assign values of incompatible types, with runtime bounds checking.)- SmartInttemplate SmartInt(N, IntFlagPolicy policy, Flag!"bitOps" bitOps = Yes.bitOps)
Wrapper for any basic integral type

`N`that uses the checked operations from`smartOp`and bounds checks assignments with`checkedint.to()`.- hasBitOpstemplate hasBitOps(T)
Evaluates to

`true`if either:`isScalarType!T`, or`isCheckedInt!T`

**And**bitwise operators such as`<<`and`~`are available for`T`.- safeOptemplate safeOp(IntFlagPolicy policy)
Implements various integer math operations with error checking.

- smartOptemplate smartOp(IntFlagPolicy policy)
Implements various integer math operations with error checking.

- totemplate to(T, IntFlagPolicy policy)
A wrapper for

`std.conv.to()`which uses`checkedint.flags`for error signaling when converting between any combination of basic scalar types and`checkedint`types. With an appropriate`policy`, this allows`checkedint.to()`to be used for numeric conversions in`pure nothrow`code, unlike`std.conv.to()`.

Checked integer arithmetic operations, functions, and types with improved handling of errors and corner cases compared to the basic integral types.

Note:Normally this module should not be imported directly. Instead, import one ofcheckedint.throws,checkedint.asserts, orcheckedint.sticky, depending on which error signalling policy is needed. (See below.)$(BIG $(B Problems solved by `checkedint`))

As in many other programming languages (C, C++, Java, etc.) D's basic integral types (such as

intorulong) are surprisingly difficult to use correctly in the general case, due to variuos departures from the behaviour of ideal mathematical integers:assert(uint.max + 1 == 0);assert(-1 > 1u);Floating Point Exception(FPE).int.min / -1andint.min % -1may also crash with an FPE, even though the latter should simply yield0.xis any integer value, andyis any negative integer value,x ^^ ywill crash with an FPE.<<,>>,>>>) is formally undefined if the shift size is less than zero or greater than(8 * N.sizeof) - 1.The

checkedintpackage offers solutions to all of these issues and more.$(BIG $(B `SafeInt` versus `SmartInt`))

Two different approaches are available:

SmartIntandsmartOpstrive to actually give the mathematically correct answer whenever possible, rather than just signaling an error.SafeIntandsafeOpstrive to match the behaviour of the basic integral types exactly,exceptthat where the behaviour of the basic type is wrong, or very unintuitive, an error is signaled instead.There is no meaningful performance difference between

SafeIntandSmartInt. For general use, choosingSmartIntsimplifies code and maximizes the range of inputs accepted.SafeIntis intended mainly as a debugging tool, to help identify problems in code that must also work correctly with the basic integral types. TheDebugInttemplatealiasmakes it simple to use ofSafeIntin debug builds, and raw basic types in release builds.int(basic type)SafeInt!intSmartInt!intint.max + 1int.minraise(IntFlag.over)raise(IntFlag.over)-1 > 1utruefalse-1 - 2u4294967293-31 / 0raise(IntFlag.div0)raise(IntFlag.div0)int.min % -1raise(IntFlag.posOver)0-1 ^^ -7raise(IntFlag.undef)-1cast(uint)-14294967295raise(IntFlag.negOver)-1 >> 100raise(IntFlag.undef)-1$(BIG $(B Error Signaling))

Some types of problem are signaled by a compile-time error, others at runtime. Runtime signaling is done through

checkedint.flags. Three different runtime signalling policies are available:IntFlagPolicy.throws, aCheckedIntExceptionis thrown. These are normal exceptions; not FPEs. As such, they can be caught and include a stack trace.IntFlagPolicy.asserts, an assertion failure will be triggered. This policy is compatible withpure nothrow @nogccode, but will crash the program in the event of a runtime integer math error.IntFlagPolicy.stickycan be selected so that a thread-local sticky flag is set when an operation fails. This allowscheckedintto be used fromnothrowand@nogc(but notpure) code without crashing the program, but requires the API user to manually insert checks ofIntFlags.local.In normal code, there is no performance penalty for allowing

checkedinttothrow. Doing so is highly recommended because this makes it easier to use correctly, and yields more precise error messages when something goes wrong.$(BIG $(B Generic Code))

The

checkedint.traitsmodule providescheckedint-aware versions of various numerical type traits fromstd.traits, such asSigned,isSignedandisIntegral. This allows writing generic algorithms that work with any ofSmartInt,SafeInt, and the built-in numeric types such asuintandlong.Also of note is the

idx()function, which concisely and safely casts from any integral type (built-in,SmartInt, orSafeInt) to eithersize_torptrdiff_tfor easy array indexing.$(BIG $(B Performance))

Replacing all basic integer types with

SmartIntorSafeIntwill slow down exectuion somewhat. How much depends on many factors, but for most code following a few simple rules should keep the penalty low:and-inline(DMD) or-O(GDC and LDC). This by itself can improve the performance of-O3checkedintby around1,000%.checkedintcan't slow down code where it's not used! For more speed, switch toDebugIntfor the hottest code in the program (like inner loops) before giving up oncheckedintentirely.The above guidelines should be more than sufficient for most programs. But, some micro-optimization are possible as well, if needed:

mulPow2(),divPow2(), andmodPow2()whenever they can naturally express the intent - they're faster than a regular/,%, orpow().checkedint, mixed signed/unsigned operations are a little bit slower than same-signedness ones.++or+=, for example) should never be slower than the equivalent two operation sequence, and are sometimes a little bit faster.References: core._checkedint