diff --git a/LICENSE-APACHEv2 b/LICENSE-APACHEv2 deleted file mode 100644 index 782d1bf..0000000 --- a/LICENSE-APACHEv2 +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2018 Status Research & Development GmbH - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/LICENSE-MIT b/LICENSE-MIT deleted file mode 100644 index 8766e65..0000000 --- a/LICENSE-MIT +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2018 Status Research & Development GmbH - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 419fb60..0000000 --- a/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Mpint (Multi-precision integers) - -[![Build Status (Travis)](https://img.shields.io/travis/status-im/mpint/master.svg?label=Linux%20/%20macOS "Linux/macOS build status (Travis)")](https://travis-ci.org/status-im/mpint) -[![License: Apache](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -![Stability: experimental](https://img.shields.io/badge/stability-experimental-orange.svg) - -A fast and portable multi-precision integer library in pure Nim - -Main focus: - - no heap/dynamic allocation - - uint256 for cryptographic and ethereum blockchain usage. - - ARM portability for usage on mobile phones - - Ease of use: - - casting to and from array of bytes - - converting to and from Hex - - converting to and from decimal strings - -## License - -Licensed under either of - - * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) - -at your option. diff --git a/src/uint_binary_ops.nim b/mem_corrupt_bug.nim similarity index 55% rename from src/uint_binary_ops.nim rename to mem_corrupt_bug.nim index 91a07d0..bc17785 100644 --- a/src/uint_binary_ops.nim +++ b/mem_corrupt_bug.nim @@ -1,21 +1,10 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import ./binary_ops/addsub_impl, - ./binary_ops/mul_impl - -export addsub_impl, mul_impl +import ./mem_corrupt_bug_add, + ./mem_corrupt_bug_mul when isMainModule: import typetraits - import ./uint_init + import ./mem_corrupt_bug_convert let a = toMpUint(10'u32) @@ -41,7 +30,7 @@ when isMainModule: # naiveMul cast16:(lo: 0, hi: 0) # +: (lo: 0, hi: 0) # Within `*` result: (lo: 100, hi: 0) -# Within `*` result: MpUint[32] -# a * a: (lo: 100, hi: 1066) +# Within `*` result type: MpUint[32] +# a * a: (lo: 100, hi: 3924) # a * a type: MpUint[32] # Is memory corrupted: true diff --git a/mem_corrupt_bug_add.nim b/mem_corrupt_bug_add.nim new file mode 100644 index 0000000..281148a --- /dev/null +++ b/mem_corrupt_bug_add.nim @@ -0,0 +1,18 @@ +import ./mem_corrupt_bug_type + +proc `+=`*(x: var MpUint, y: MpUint) = + ## In-place addition for multi-precision unsigned int + type SubT = type x.lo + let tmp = x.lo + + x.lo += y.lo + x.hi += SubT(x.lo < tmp) + y.hi + +proc `+`*(x, y: MpUint): MpUint = + # Addition for multi-precision unsigned int + result = x + result += y + + debugEcho "+: " & $result + + diff --git a/mem_corrupt_bug_convert.nim b/mem_corrupt_bug_convert.nim new file mode 100644 index 0000000..d24ba90 --- /dev/null +++ b/mem_corrupt_bug_convert.nim @@ -0,0 +1,13 @@ +import ./mem_corrupt_bug_type + +# Commenting the uint16 proc (that is never called) +# Or +# Removing the inline pragma of the uint32 proc solves the issue + +proc toMpUint*(n: uint16): MpUint[16] {.inline.}= + ## Cast an integer to the corresponding size MpUint + cast[MpUint[16]](n) + +proc toMpUint*(n: uint32): MpUint[32] {.inline.}= + ## Cast an integer to the corresponding size MpUint + cast[MpUint[32]](n) diff --git a/mem_corrupt_bug_mul.nim b/mem_corrupt_bug_mul.nim new file mode 100644 index 0000000..7f95848 --- /dev/null +++ b/mem_corrupt_bug_mul.nim @@ -0,0 +1,26 @@ + +import ./mem_corrupt_bug_type, ./mem_corrupt_bug_convert +import ./mem_corrupt_bug_add + +import typetraits + +# Comment the following to remove the memory corruption +proc naiveMul*(x, y: uint8): MpUint[16] = + # Multiplication in extended precision + result = toMpuint(x.uint16 * y.uint16) + +proc naiveMul*(x, y: uint16): MpUint[32] = + # Multiplication in extended precision + result = toMpuint(x.uint32 * y.uint32) + debugEcho "naiveMul cast16:" & $result + +proc `*`*(x, y: MpUint): MpUint = + ## Multiplication for multi-precision unsigned uint + + result = naiveMul(x.lo, y.lo) + result.hi += (naiveMul(x.hi, y.lo) + naiveMul(x.lo, y.hi)).lo + + debugEcho "Within `*` result: " & $result + debugEcho "Within `*` result type: " & $result.type.name + + diff --git a/mem_corrupt_bug_type.nim b/mem_corrupt_bug_type.nim new file mode 100644 index 0000000..618d8da --- /dev/null +++ b/mem_corrupt_bug_type.nim @@ -0,0 +1,15 @@ +type + # TODO: The following is a hacky workaround + # due to: + # - https://github.com/nim-lang/Nim/issues/7230 + # - https://github.com/nim-lang/Nim/issues/7378 + # - https://github.com/nim-lang/Nim/issues/7379 + + BitsHolder[bits: static[int]] = object + +type + MpUintImpl[bh] = object + when bh is BitsHolder[32]: lo*, hi*: uint16 + elif bh is BitsHolder[16]: lo*, hi*: uint8 + + MpUint*[bits: static[int]] = MpUintImpl[BitsHolder[bits]] diff --git a/mpint.nimble b/mpint.nimble deleted file mode 100644 index cbef02f..0000000 --- a/mpint.nimble +++ /dev/null @@ -1,23 +0,0 @@ -packageName = "mpint" -version = "0.0.1" -author = "Status Research & Development GmbH" -description = "Efficient multiprecision int in Nim" -license = "Apache License 2.0 or MIT" -srcDir = "src" - -### Dependencies - -requires "nim >= 0.18" - -proc test(name: string, lang: string = "c") = - if not dirExists "build": - mkDir "build" - if not dirExists "nimcache": - mkDir "nimcache" - --run - --nimcache: "nimcache" - switch("out", ("./build/" & name)) - setCommand lang, "tests/" & name & ".nim" - -task test, "Run all tests": - test "all_tests" diff --git a/src/binary_ops/addsub_impl.nim b/src/binary_ops/addsub_impl.nim deleted file mode 100644 index 80aa3c0..0000000 --- a/src/binary_ops/addsub_impl.nim +++ /dev/null @@ -1,45 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import ../uint_type - -proc `+=`*(x: var MpUint, y: MpUint) {.noSideEffect.}= - ## In-place addition for multi-precision unsigned int - # - # Optimized assembly should contain adc instruction (add with carry) - # Clang on MacOS does with the -d:release switch and MpUint[uint32] (uint64) - type SubT = type x.lo - let tmp = x.lo - - x.lo += y.lo - x.hi += SubT(x.lo < tmp) + y.hi - -proc `+`*(x, y: MpUint): MpUint {.noSideEffect, noInit, inline.}= - # Addition for multi-precision unsigned int - result = x - result += y - - debugEcho "+: " & $result - -proc `-=`*(x: var MpUint, y: MpUint) {.noSideEffect.}= - ## In-place substraction for multi-precision unsigned int - # - # Optimized assembly should contain sbb instruction (substract with borrow) - # Clang on MacOS does with the -d:release switch and MpUint[uint32] (uint64) - type SubT = type x.lo - let tmp = x.lo - - x.lo -= y.lo - x.hi -= SubT(x.lo > tmp) + y.hi - -proc `-`*(x, y: MpUint): MpUint {.noSideEffect, noInit, inline.}= - # Substraction for multi-precision unsigned int - result = x - result -= y - diff --git a/src/binary_ops/div_impl.nim b/src/binary_ops/div_impl.nim deleted file mode 100644 index da9e639..0000000 --- a/src/binary_ops/div_impl.nim +++ /dev/null @@ -1,56 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -# proc divmod*(x, y: MpUint): tuple[quot, rem: MpUint] {.noSideEffect.}= -# ## Division for multi-precision unsigned uint -# ## Returns quotient + reminder in a (quot, rem) tuple -# # -# # Implementation through binary shift division -# const zero = T() - -# when x.lo is MpUInt: -# const one = T(lo: getSubType(T)(1)) -# else: -# const one: getSubType(T) = 1 - -# if unlikely(y.isZero): -# raise newException(DivByZeroError, "You attempted to divide by zero") - -# var -# shift = x.bit_length - y.bit_length -# d = y shl shift - -# result.rem = x - -# while shift >= 0: -# result.quot += result.quot -# if result.rem >= d: -# result.rem -= d -# result.quot.lo = result.quot.lo or one - -# d = d shr 1 -# dec(shift) - -# # Performance note: -# # The performance of this implementation is extremely dependant on shl and shr. -# # -# # Probably the most efficient algorithm that can benefit from MpUInt data structure is -# # the recursive fast division by Burnikel and Ziegler (http://www.mpi-sb.mpg.de/~ziegler/TechRep.ps.gz): -# # - Python implementation: https://bugs.python.org/file11060/fast_div.py and discussion https://bugs.python.org/issue3451 -# # - C++ implementation: https://github.com/linbox-team/givaro/blob/master/src/kernel/recint/rudiv.h -# # - The Handbook of Elliptic and Hyperelliptic Cryptography Algorithm 10.35 on page 188 has a more explicit version of the div2NxN algorithm. This algorithm is directly recursive and avoids the mutual recursion of the original paper's calls between div2NxN and div3Nx2N. -# # - Comparison of fast division algorithms fro large integers: http://bioinfo.ict.ac.cn/~dbu/AlgorithmCourses/Lectures/Hasselstrom2003.pdf - -# proc `div`*(x, y: MpUint): MpUint {.inline, noSideEffect.} = -# ## Division operation for multi-precision unsigned uint -# divmod(x,y).quot - -# proc `mod`*(x, y: MpUint): MpUint {.inline, noSideEffect.} = -# ## Division operation for multi-precision unsigned uint -# divmod(x,y).rem diff --git a/src/binary_ops/mul_impl.nim b/src/binary_ops/mul_impl.nim deleted file mode 100644 index ec03bc4..0000000 --- a/src/binary_ops/mul_impl.nim +++ /dev/null @@ -1,32 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import ../uint_type, ../uint_init -import ./addsub_impl - -import typetraits - -proc `*`*(x, y: MpUint): MpUint {.noSideEffect.}= - ## Multiplication for multi-precision unsigned uint - - mixin naiveMul - - result = naiveMul(x.lo, y.lo) - result.hi += (naiveMul(x.hi, y.lo) + naiveMul(x.lo, y.hi)).lo - - debugEcho "Within `*` result: " & $result - debugEcho "Within `*` result: " & $result.type.name - -# Comment the following to remove the memory corruption -proc naiveMul*(x, y: uint8): MpUint[16] {.noSideEffect.}= - result = toMpuint(x.uint16 * y.uint16) - -proc naiveMul*(x, y: uint16): MpUint[32] {.noSideEffect.}= - result = toMpuint(x.uint32 * y.uint32) - debugEcho "naiveMul cast16:" & $result diff --git a/src/mpint.nim b/src/mpint.nim deleted file mode 100644 index de75aeb..0000000 --- a/src/mpint.nim +++ /dev/null @@ -1,20 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import ./uint_type, - ./uint_init - #./uint_bitwise_ops, - #./uint_binary_ops, - #./uint_comparison - -export uint_type, - uint_init - # uint_bitwise_ops, - # uint_binary_ops, - # uint_comparison diff --git a/src/uint_init.nim b/src/uint_init.nim deleted file mode 100644 index 59d0d00..0000000 --- a/src/uint_init.nim +++ /dev/null @@ -1,39 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import typetraits - -import ./uint_type - -proc toMpUint*(n: uint16): MpUint[16] {.noInit, inline, noSideEffect.}= - ## Cast an integer to the corresponding size MpUint - cast[MpUint[16]](n) - -proc toMpUint*(n: uint32): MpUint[32] {.noInit, inline, noSideEffect.}= - ## Cast an integer to the corresponding size MpUint - cast[MpUint[32]](n) - -proc toMpUint*(n: uint64): MpUint[64] {.noInit, inline, noSideEffect.}= - ## Cast an integer to the corresponding size MpUint - cast[MpUint[64]](n) - -proc initMpUint*(n: SomeUnsignedInt, bits: static[int]): MpUint[bits] {.noSideEffect.} = - - const nb_bits = n.sizeof * 8 - - static: - assert (bits and (bits-1)) == 0, $bits & " is not a power of 2" - assert bits >= 16, "The number of bits in a should be greater or equal to 16" - assert nb_bits <= bits, "Input cannot be stored in a " & $bits "-bit multi-precision unsigned integer\n" & - "It requires at least " & nb_bits & " bits of precision" - - when nb_bits <= bits div 2: - result.lo = (type result.lo)(n) - else: - result = n.toMpUint diff --git a/src/uint_type.nim b/src/uint_type.nim deleted file mode 100644 index 674e2d3..0000000 --- a/src/uint_type.nim +++ /dev/null @@ -1,43 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -type - # TODO: The following is a hacky workaround - # due to: - # - https://github.com/nim-lang/Nim/issues/7230 - # - https://github.com/nim-lang/Nim/issues/7378 - # - https://github.com/nim-lang/Nim/issues/7379 - - BitsHolder[bits: static[int]] = object - -type - MpUintImpl[bh] = object - # TODO: when gcc/clang defines it use the builtin uint128 - when system.cpuEndian == littleEndian: - when bh is BitsHolder[128]: lo*, hi*: uint64 - elif bh is BitsHolder[64]: lo*, hi*: uint32 - elif bh is BitsHolder[32]: lo*, hi*: uint16 - elif bh is BitsHolder[16]: lo*, hi*: uint8 - - # The following cannot be implemented recursively yet - elif bh is BitsHolder[256]: lo*, hi*: MpUintImpl[BitsHolder[128]] - # else: - # Not implemented - else: - when bh is BitsHolder[128]: hi*, lo*: uint64 - elif bh is BitsHolder[64]: hi*, lo*: uint32 - elif bh is BitsHolder[32]: hi*, lo*: uint16 - elif bh is BitsHolder[16]: hi*, lo*: uint8 - - # The following cannot be implemented recursively yet - elif bh is BitsHolder[256]: hi*, lo*: MpUintImpl[BitsHolder[128]] - # else: - # Not implemented - - MpUint*[bits: static[int]] = MpUintImpl[BitsHolder[bits]] diff --git a/tests/all_tests.nim b/tests/all_tests.nim deleted file mode 100644 index 785a027..0000000 --- a/tests/all_tests.nim +++ /dev/null @@ -1,13 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import test_endianness, - test_comparison, - test_addsub, - test_muldiv diff --git a/tests/test_addsub.nim b/tests/test_addsub.nim deleted file mode 100644 index 5186752..0000000 --- a/tests/test_addsub.nim +++ /dev/null @@ -1,76 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import ../src/mpint, unittest - -suite "Testing addition implementation": - test "In-place addition gives expected result": - - var a = initMpUint(20182018, uint32) - let b = initMpUint(20172017, uint32) - - a += b - - check: cast[uint64](a) == 20182018'u64 + 20172017'u64 - - test "Addition gives expected result": - - let a = initMpUint(20182018, uint32) - let b = initMpUint(20172017, uint32) - - check: cast[uint64](a+b) == 20182018'u64 + 20172017'u64 - - test "When the low half overflows, it is properly carried": - # uint8 (low half) overflow at 255 - let a = initMpUint(100, uint8) - let b = initMpUint(100, uint8) - - check: cast[uint16](a+b) == 200 - - test "Full overflow is handled like native unsigned types": - # uint16 overflows after 65535 - let a = initMpUint(100, uint8) - var z = initMpUint(0, uint8) - let o = initMpUint(36, uint8) - - for _ in 0 ..< 655: - z += a - - check: cast[uint16](z) == 65500 - check: cast[uint16](z + o) == 0 - - z += a - check: cast[uint16](z) == 64 - - z += a - check: cast[uint16](z) == 164 - -suite "Testing substraction implementation": - test "In-place substraction gives expected result": - - var a = initMpUint(20182018, uint32) - let b = initMpUint(20172017, uint32) - - a -= b - - check: cast[uint64](a) == 20182018'u64 - 20172017'u64 - - test "Substraction gives expected result": - - let a = initMpUint(20182018, uint32) - let b = initMpUint(20172017, uint32) - - check: cast[uint64](a-b) == 20182018'u64 - 20172017'u64 - - test "Full overflow is handled like native unsigned types": - # uint16 overflows after 65535 - let a = initMpUint(100, uint8) - let b = initMpUint(101, uint8) - - check: cast[uint16](a-b) == high(uint16) diff --git a/tests/test_bitwise.nim b/tests/test_bitwise.nim deleted file mode 100644 index 2633c89..0000000 --- a/tests/test_bitwise.nim +++ /dev/null @@ -1,40 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import ../src/mpint, unittest - -suite "Testing bitwise operations": - let a = initMpUint(100, uint8) - - let b = a * a - let z = 10000'u16 - - test "Shift left - by less than half the size of the integer": - check: cast[uint16](b) == z # Sanity check - check: cast[uint16](b shl 2) == z shl 2 - - test "Shift left - by more than half the size of the integer": - check: cast[uint16](b) == z # Sanity check - check: cast[uint16](b shl 10) == z shl 10 - - test "Shift left - by half the size of the integer": - check: cast[uint16](b) == z # Sanity check - check: cast[uint16](b shl 8) == z shl 8 - - test "Shift right - by less than half the size of the integer": - check: cast[uint16](b) == z # Sanity check - check: cast[uint16](b shr 2) == z shr 2 - - test "Shift right - by more than half the size of the integer": - check: cast[uint16](b) == z # Sanity check - check: cast[uint16](b shr 10) == z shr 10 - - test "Shift right - by half the size of the integer": - check: cast[uint16](b) == z # Sanity check - check: cast[uint16](b shr 8) == z shr 8 diff --git a/tests/test_comparison.nim b/tests/test_comparison.nim deleted file mode 100644 index ae6b4cf..0000000 --- a/tests/test_comparison.nim +++ /dev/null @@ -1,40 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import ../src/mpint, unittest - -suite "Testing comparison operators": - let - a = initMpUint(10, uint8) - b = initMpUint(15, uint8) - c = 150'u16 - - test "< operator": - check: a < b - check: not (a + b < b) - check: not (a + a + a < b + b) - check: not (a * b < cast[Mpuint[uint8]](c)) - - test "<= operator": - check: a <= b - check: not (a + b <= b) - check: a + a + a <= b + b - check: a * b <= cast[Mpuint[uint8]](c) - - test "> operator": - check: b > a - check: not (b > a + b) - check: not (b + b > a + a + a) - check: not (cast[Mpuint[uint8]](c) > a * b) - - test ">= operator": - check: b >= a - check: not (b >= a + b) - check: b + b >= a + a + a - check: cast[Mpuint[uint8]](c) >= a * b diff --git a/tests/test_endianness.nim b/tests/test_endianness.nim deleted file mode 100644 index 9692bb8..0000000 --- a/tests/test_endianness.nim +++ /dev/null @@ -1,20 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import ../src/mpint, unittest - -suite "Testing byte representation": - test "Byte representation conforms to the platform endianness": - let a = initMpUint(20182018, uint32) - let b = 20182018'u64 - - type AsBytes = array[8, byte] - - check cast[AsBytes](a) == cast[AsBytes](b) - diff --git a/tests/test_muldiv.nim b/tests/test_muldiv.nim deleted file mode 100644 index a8a2074..0000000 --- a/tests/test_muldiv.nim +++ /dev/null @@ -1,44 +0,0 @@ -# Mpint -# Copyright 2018 Status Research & Development GmbH -# Licensed under either of -# -# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) -# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) -# -# at your option. This file may not be copied, modified, or distributed except according to those terms. - -import ../src/mpint, unittest - -suite "Testing multiplication implementation": - test "Multiplication with result fitting in low half": - - let a = initMpUint(10000, uint32) - let b = initMpUint(10000, uint32) - - check: cast[uint64](a*b) == 100_000_000'u64 # need 27-bits - - test "Multiplication with result overflowing low half": - - let a = initMpUint(1_000_000, uint32) - let b = initMpUint(1_000_000, uint32) - - check: cast[uint64](a*b) == 1_000_000_000_000'u64 # need 40 bits - - test "Full overflow is handled like native unsigned types": - - let a = initMpUint(1_000_000_000, uint32) - let b = initMpUint(1_000_000_000, uint32) - let c = initMpUint(1_000, uint32) - - check: cast[uint64](a*b*c) == 1_000_000_000_000_000_000_000'u64 # need 70-bits - - -suite "Testing division and modulo implementation": - test "Divmod returns the correct result": - - let a = initMpUint(100, uint32) - let b = initMpUint(13, uint32) - let qr = a.divmod(b) - - check: cast[uint64](qr.quot) == 7'u64 - check: cast[uint64](qr.rem) == 9'u64