summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2016-12-08 18:30:22 +0100
committerEugen Wissner <belka@caraus.de>2016-12-08 18:30:22 +0100
commita2dadda511282f5c4a103921a9a9ad388a5e0c0a (patch)
tree141383a7e29e6f775e78616b74a8c92304e1e643
parent77dca312612a68c774d7e593b855ca67614f9feb (diff)
downloadtanya-a2dadda511282f5c4a103921a9a9ad388a5e0c0a.tar.gz
Fix subtraction of numbers with different signs
-rw-r--r--README.md12
-rw-r--r--source/tanya/math/mp.d89
-rw-r--r--source/tanya/memory/types.d4
3 files changed, 62 insertions, 43 deletions
diff --git a/README.md b/README.md
index 8527dba..63d8886 100644
--- a/README.md
+++ b/README.md
@@ -3,14 +3,18 @@
[![Build Status](https://travis-ci.org/caraus-ecms/tanya.svg?branch=master)](https://travis-ci.org/caraus-ecms/tanya)
[![License](http://img.shields.io/badge/license-MPL2-blue.svg)](https://raw.githubusercontent.com/caraus-ecms/tanya/master/LICENSE)
-tanya is a general purpose library for D programming language that doesn't rely on the Garbage Collector.
+Tanya is a general purpose library for D programming language that doesn't
+rely on the Garbage Collector.
-# Overview
+The library is currently in development.
-The library consists of the following packages:
+## Overview
+
+Tanya consists of the following packages:
* `async`: Event loop.
-* `containers`: Queue, Vector, Singly linked list.
+* `container`: Queue, Vector, Singly linked list.
* `crypto`: Work in progress TLS implementation.
+* `math`: Multiple precision integer and a set of functions.
* `memory`: Tools for manual memory management (allocator, reference counting, helper functions).
* `network`: URL-Parsing, sockets.
diff --git a/source/tanya/math/mp.d b/source/tanya/math/mp.d
index 5c89c6b..6da1027 100644
--- a/source/tanya/math/mp.d
+++ b/source/tanya/math/mp.d
@@ -18,9 +18,12 @@ import std.range;
import std.traits;
import tanya.memory;
+/**
+ * Mutliple precision integer.
+ */
struct Integer
{
- private RefCounted!(ubyte[]) rep;
+ private RefCounted!(ubyte[]) rep;
private bool sign;
private shared Allocator allocator;
@@ -47,11 +50,7 @@ struct Integer
body
{
this(allocator);
-
- T absolute = value;
- immutable size = calculateSizeFromInt(absolute);
- allocator.resizeArray(rep, size);
- assignInt(absolute);
+ assignInt(value);
}
private @nogc unittest
@@ -93,10 +92,10 @@ struct Integer
/*
* Figures out the minimum amount of space this value will take
- * up in bytes. Set the sign.
+ * up in bytes and resizes the internal storage. Sets the sign.
*/
- private ubyte calculateSizeFromInt(T)(ref T value)
- pure nothrow @safe @nogc
+ private void assignInt(T)(in ref T value)
+ nothrow @safe @nogc
in
{
static assert(isIntegral!T);
@@ -104,40 +103,36 @@ struct Integer
body
{
ubyte size = ulong.sizeof;
+ ulong mask;
static if (isSigned!T)
{
sign = value < 0 ? true : false;
- value = abs(value);
+ immutable absolute = value.abs;
}
else
{
sign = false;
+ alias absolute = value;
}
- for (ulong mask = 0xff00000000000000; mask >= 0xff; mask >>= 8)
+ for (mask = 0xff00000000000000; mask >= 0xff; mask >>= 8)
{
- if (value & mask)
+ if (absolute & mask)
{
break;
}
--size;
}
- return size;
- }
-
- /*
- * Work backward through the int, masking off each byte
- * (up to the first 0 byte) and copy it into the internal
- * representation in big-endian format.
- */
- private void assignInt(in ulong value)
- pure nothrow @safe @nogc
- {
- ulong mask = 0xff;
+ allocator.resizeArray(rep.get, size);
+
+ /* Work backward through the int, masking off each byte (up to the
+ first 0 byte) and copy it into the internal representation in
+ big-endian format. */
+ mask = 0xff;
ushort shift;
- for (auto i = length; i; --i, mask <<= 8, shift += 8)
+ for (auto i = rep.length; i; --i, mask <<= 8, shift += 8)
{
- rep[i - 1] = cast(ubyte) ((value & mask) >> shift);
+ rep[i - 1] = cast(ubyte) ((absolute & mask) >> shift);
}
}
@@ -153,12 +148,8 @@ struct Integer
ref Integer opAssign(T)(in T value) nothrow @safe @nogc
if (isIntegral!T)
{
- T absolute = value;
- immutable size = calculateSizeFromInt(absolute);
-
checkAllocator();
- allocator.resizeArray(rep.get, size);
- assignInt(absolute);
+ assignInt(value);
return this;
}
@@ -278,8 +269,6 @@ struct Integer
uint sum;
uint carry = 0;
- // Adding h2 to h1. If h2 is > h1 to begin with, resize h1
-
if (h.length > length)
{
auto tmp = allocator.makeArray!ubyte(h.length);
@@ -311,7 +300,7 @@ struct Integer
{
// Still overflowed; allocate more space
auto tmp = allocator.makeArray!ubyte(length + 1);
- tmp[1..$] = rep[0..length];
+ tmp[1 .. $] = rep[0..length];
tmp[0] = 0x01;
rep = tmp;
}
@@ -373,6 +362,11 @@ struct Integer
*/
ref Integer opOpAssign(string op)(in Integer h) nothrow @safe @nogc
if ((op == "+") || (op == "-"))
+ out
+ {
+ assert(!rep.length || rep[0]);
+ }
+ body
{
checkAllocator();
static if (op == "+")
@@ -414,7 +408,7 @@ struct Integer
}
else
{
- subtract(h.rep);
+ add(h.rep);
}
}
return this;
@@ -481,6 +475,11 @@ struct Integer
/// Ditto.
ref Integer opOpAssign(string op)(in Integer h) nothrow @safe @nogc
if (op == "*")
+ out
+ {
+ assert(!rep.length || rep[0]);
+ }
+ body
{
auto i = h.rep.length;
auto temp = Integer(this, allocator);
@@ -598,6 +597,11 @@ struct Integer
/// Ditto.
ref Integer opOpAssign(string op)(in Integer exp) nothrow @safe @nogc
if (op == "^^")
+ out
+ {
+ assert(!rep.length || rep[0]);
+ }
+ body
{
auto i = exp.rep.length;
auto tmp1 = Integer(this, allocator);
@@ -738,6 +742,11 @@ struct Integer
*/
ref Integer opUnary(string op)() nothrow @safe @nogc
if ((op == "++") || (op == "--"))
+ out
+ {
+ assert(!rep.length || rep[0]);
+ }
+ body
{
checkAllocator();
@@ -878,6 +887,11 @@ struct Integer
*/
ref Integer opOpAssign(string op)(in size_t n) nothrow @safe @nogc
if (op == ">>")
+ out
+ {
+ assert(!rep.length || rep[0]);
+ }
+ body
{
immutable step = n / 8;
@@ -950,6 +964,11 @@ struct Integer
/// Ditto.
ref Integer opOpAssign(string op)(in size_t n) nothrow @safe @nogc
if (op == "<<")
+ out
+ {
+ assert(!rep.length || rep[0]);
+ }
+ body
{
ubyte carry;
auto i = rep.length;
diff --git a/source/tanya/memory/types.d b/source/tanya/memory/types.d
index 19c1e4b..1c899be 100644
--- a/source/tanya/memory/types.d
+++ b/source/tanya/memory/types.d
@@ -316,10 +316,6 @@ private unittest
* $(D_PSYMBOL RefCounted) using $(D_PARAM args) as the parameter list for
* the constructor of $(D_PARAM T).
*
- * This function is more efficient than using $(D_PSYMBOL RefCounted)
- * for the new objects directly, since $(D_PSYMBOL refCounted) allocates
- * only once (the object and the internal storage are allocated at once).
- *
* Params:
* T = Type of the constructed object.
* A = Types of the arguments to the constructor of $(D_PARAM T).