gmp: Introduce NativeMPZ and NativeMPQ with simple test
authorPatrickBlanchette <PatrickBlanchette@users.noreply.github.com>
Mon, 15 May 2017 13:56:46 +0000 (09:56 -0400)
committerPatrickBlanchette <PatrickBlanchette@users.noreply.github.com>
Wed, 31 May 2017 18:24:26 +0000 (14:24 -0400)
Signed-off-by: PatrickBlanchette <PatrickBlanchette@users.noreply.github.com>

lib/gmp/native_gmp.nit [new file with mode: 0644]
lib/gmp/test_native_gmp.nit [new file with mode: 0644]

diff --git a/lib/gmp/native_gmp.nit b/lib/gmp/native_gmp.nit
new file mode 100644 (file)
index 0000000..8c8b86a
--- /dev/null
@@ -0,0 +1,262 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# 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.
+
+# Low-level GMP features
+module native_gmp is ldflags("-lgmp")
+
+in "C header" `{
+    #include <gmp.h>
+`}
+
+# Multi precision Integer
+extern class NativeMPZ `{mpz_ptr`}
+
+    # Initializing
+
+    new `{
+        mpz_ptr self =  (mpz_ptr)malloc(sizeof(mpz_t));
+        mpz_init(self);
+        return self;
+    `}
+
+    # Arithmetic Functions
+
+    fun add(res, op: NativeMPZ) `{
+        mpz_add(res, self, op);
+    `}
+
+    fun add_ui(res: NativeMPZ, op: UInt64) `{
+        mpz_add_ui(res, self, *op);
+    `}
+
+    fun sub(res, op: NativeMPZ) `{
+        mpz_sub(res, self, op);
+    `}
+
+    fun sub_ui(res: NativeMPZ, op: UInt64) `{
+        mpz_sub_ui(res, self, *op);
+    `}
+
+    fun mul(res, op: NativeMPZ) `{
+        mpz_mul(res, self, op);
+    `}
+
+    fun mul_si(res: NativeMPZ, op: Int) `{
+        mpz_mul_si(res, self, op);
+    `}
+
+    fun neg(res: NativeMPZ) `{
+        mpz_neg(res, self);
+    `}
+
+    fun abs(res: NativeMPZ) `{
+        mpz_abs(res, self);
+    `}
+
+    fun tdiv_q(res, op: NativeMPZ) `{
+        mpz_tdiv_q(res, self, op);
+    `}
+
+    fun tdiv_q_ui(res: NativeMPZ, op: UInt64) `{
+        mpz_tdiv_q_ui(res, self, *op);
+    `}
+
+    fun mod(res, op: NativeMPZ) `{
+        mpz_mod(res, self, op);
+    `}
+
+    fun mod_ui(res: NativeMPZ, op: UInt64) `{
+        mpz_mod_ui(res, self, *op);
+    `}
+
+    fun pow_ui(res: NativeMPZ, op: UInt64) `{
+        mpz_pow_ui(res, self, *op);
+    `}
+
+    #Number Theoretic Functions
+
+    fun probab_prime_p(reps: Int32): Int `{
+        return mpz_probab_prime_p(self, reps);
+    `}
+
+    fun nextprime(res: NativeMPZ) `{
+        mpz_nextprime(res, self);
+    `}
+
+    fun gcd(res, op: NativeMPZ) `{
+        mpz_gcd(res, self, op);
+    `}
+
+    fun gcd_ui(res: NativeMPZ, op: UInt64) `{
+        mpz_gcd_ui(res, self, *op);
+    `}
+
+    # Comparison Functions
+
+    fun cmp(op: NativeMPZ): Int `{
+        return mpz_cmp(self, op);
+    `}
+
+    fun cmp_si(op: Int): Int `{
+        return mpz_cmp_si(self, op);
+    `}
+
+    # Assignment
+
+    fun set(op: NativeMPZ) `{ mpz_set(self, op); `}
+
+    fun set_si(op: Int) `{ mpz_set_si(self, op); `}
+
+    fun set_d(op: Float) `{ mpz_set_d(self, op); `}
+
+    fun set_q(op: NativeMPQ) `{ mpz_set_q(self, op); `}
+
+    fun set_str(str: CString, base: Int32) `{
+        mpz_set_str(self, str, base);
+    `}
+
+    fun swap(op: NativeMPZ) `{ mpz_swap(self, op); `}
+
+    # Conversion Functions
+
+    fun get_si: Int `{ return mpz_get_si(self); `}
+
+    fun get_d: Float `{ return mpz_get_d(self); `}
+
+    fun get_str(base: Int32): CString `{
+        return mpz_get_str(NULL, base, self);
+    `}
+
+    # Delete this NativeMPZ
+    fun finalize `{
+        mpz_clear(self);
+        free(self);
+    `}
+end
+
+# Multi precision Rational
+extern class NativeMPQ `{mpq_ptr`}
+
+    # Initializing
+
+    new `{
+        mpq_ptr self = (mpq_ptr)malloc(sizeof(mpq_t));
+        mpq_init(self);
+        return self;
+    `}
+
+    # Arithmetic Functions
+
+    fun add(res, op: NativeMPQ) `{
+        mpq_add(res, self, op);
+    `}
+
+    fun sub(res, op: NativeMPQ) `{
+        mpq_sub(res, self, op);
+    `}
+
+    fun mul(res, op: NativeMPQ) `{
+        mpq_mul(res, self, op);
+    `}
+
+    fun div(res, op: NativeMPQ) `{
+        mpq_div(res, self, op);
+    `}
+
+    fun neg(res: NativeMPQ) `{
+        mpq_neg(res, self);
+    `}
+
+    fun abs(res: NativeMPQ) `{
+        mpq_abs(res, self);
+    `}
+
+    fun inv(res: NativeMPQ) `{
+        mpq_inv(res, self);
+    `}
+
+    # Assignment
+
+    fun set(op: NativeMPQ) `{ mpq_set(self, op); `}
+
+    fun set_z(op: NativeMPZ) `{ mpq_set_z(self, op); `}
+
+    fun set_si(op1: Int, op2: Int) `{
+        mpq_set_si(self, op1, op2);
+        mpq_canonicalize(self);
+    `}
+
+    fun set_d(op: Float) `{ mpq_set_d(self, op); `}
+
+    fun set_str(str: CString) `{
+        mpq_set_str(self, str, 10);
+        mpq_canonicalize(self);
+    `}
+
+    fun swap(op: NativeMPQ) `{ mpq_swap(self, op); `}
+
+    # Convertion Functions
+
+    fun get_d: Float `{ return mpq_get_d(self); `}
+
+    fun get_str(base: Int32): CString `{
+        return mpq_get_str(NULL, base, self);
+    `}
+
+    # Comparison Functions
+
+    fun cmp(op: NativeMPQ): Int `{
+        return mpq_cmp(self, op);
+    `}
+
+#    fun cmp_z(op: NativeMPZ): Int `{
+#        return mpq_cmp_z(self, op);
+#    `}
+
+    fun cmp_si(num: Int, den: Int): Int `{
+        return mpq_cmp_si(self, num, den);
+    `}
+
+    fun equal(op: NativeMPQ): Bool `{
+        return mpq_equal(self, op);
+    `}
+
+    # Getter
+
+    fun numref: NativeMPZ `{
+        return mpq_numref(self);
+    `}
+
+    fun denref: NativeMPZ `{
+        return mpq_denref(self);
+    `}
+
+    # Delete this NativeMPZ
+    fun finalize `{
+        mpq_clear(self);
+        free(self);
+    `}
+end
+
+# Boxing of C Unsigned Long
+extern class UInt64 `{ uint64_t* `}
+    new `{
+        uint64_t *self = (uint64_t*)malloc(sizeof(uint64_t));
+        return self;
+    `}
+
+    fun set_si(val: Int) `{
+        *self = (uint64_t)val;
+    `}
+end
diff --git a/lib/gmp/test_native_gmp.nit b/lib/gmp/test_native_gmp.nit
new file mode 100644 (file)
index 0000000..b27a3c0
--- /dev/null
@@ -0,0 +1,361 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# 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.
+
+module test_native_gmp is test_suite
+
+import test_suite
+import native_gmp
+
+class TestNativeMPZ
+    super TestSuite
+
+    var op1: NativeMPZ
+    var op2: NativeMPZ
+    var ui: UInt64
+    var r: NativeMPQ
+    var res: NativeMPZ
+
+    init do end
+
+    redef fun before_test do
+        op1 = new NativeMPZ
+        op2 = new NativeMPZ
+        ui = new UInt64
+        r = new NativeMPQ
+        res = new NativeMPZ
+    end
+
+    redef fun after_test do
+        op1.finalize
+        op2.finalize
+        ui.free
+        r.finalize
+        res.finalize
+    end
+
+    fun test_add do
+        op1.set_si 10
+        op2.set_si 20
+        op1.add(res, op2)
+        assert(res.cmp_si(30) == 0)
+    end
+
+    fun test_add_ui do
+        op1.set_si 10
+        ui.set_si 20
+        op1.add_ui(res, ui)
+        assert(res.cmp_si(30) == 0)
+    end
+
+    fun test_sub do
+        op1.set_si 30
+        op2.set_si 20
+        op1.sub(res, op2)
+        assert(res.cmp_si(10) == 0)
+    end
+
+    fun test_sub_ui do
+        op1.set_si 30
+        ui.set_si 20
+        op1.sub_ui(res, ui)
+        assert(res.cmp_si(10) == 0)
+    end
+
+    fun test_mul do
+        op1.set_si 10
+        op2.set_si 2
+        op1.mul(res, op2)
+        assert(res.cmp_si(20) == 0)
+    end
+
+    fun test_mul_si do
+        op1.set_si 2
+        op1.mul_si(res, 20)
+        assert(res.cmp_si(40) == 0)
+    end
+
+    fun test_neg do
+        op1.set_si 10
+        op1.neg(res)
+        assert(res.cmp_si(-10) == 0)
+    end
+
+    fun test_abs do
+        op1.set_si -10
+        op1.abs(res)
+        assert(res.cmp_si(10) == 0)
+    end
+
+    fun test_tdiv_q do
+        op1.set_si 11
+        op2.set_si 2
+        op1.tdiv_q(res, op2)
+        assert(res.cmp_si(5) == 0)
+    end
+
+    fun test_tdiv_q_ui do
+        op1.set_si 20
+        ui.set_si 20
+        op1.tdiv_q_ui(res, ui)
+        assert(res.cmp_si(1) == 0)
+    end
+
+    fun test_mod do
+        op1.set_si 11
+        op2.set_si 2
+        op1.mod(res, op2)
+        assert(res.cmp_si(1) == 0)
+    end
+
+    fun test_mod_ui do
+        op1.set_si 20
+        ui.set_si 20
+        op1.mod_ui(res, ui)
+        assert(res.cmp_si(0) == 0)
+    end
+
+    fun test_probab_prime_p do
+        op1.set_si 11
+        assert(op1.probab_prime_p(10i32) == 2)
+    end
+
+    fun test_nextprime do
+        op1.set_si 7
+        op1.nextprime res
+        assert(res.cmp_si(11) == 0)
+    end
+
+    fun test_gcd do
+        op1.set_si 12
+        op2.set_si 8
+        op1.gcd(res, op2)
+        assert(res.cmp_si(4) == 0)
+    end
+
+    fun test_gcd_ui do
+        op1.set_si 30
+        ui.set_si 20
+        op1.gcd_ui(res, ui)
+        assert(res.cmp_si(10) == 0)
+    end
+
+    fun test_cmp do
+        op1.set_si 12
+        op2.set_si 12
+        assert(op1.cmp(op2) == 0)
+    end
+
+    fun test_cmp_si do
+        op1.set_si 30
+        assert(op1.cmp_si(30) == 0)
+    end
+
+    fun test_set do
+        op1.set_si 12
+        op2.set op1
+        assert(op1.cmp(op2) == 0)
+    end
+
+    fun test_set_si do
+        op1.set_si 30
+        assert(op1.cmp_si(30) == 0)
+    end
+
+    fun test_set_d do
+        op1.set_d 3.0
+        assert(op1.cmp_si(3) == 0)
+    end
+
+    fun test_set_q do
+        r.set_si(30, 1)
+        op1.set_q r
+        assert(op1.cmp_si(30) == 0)
+    end
+
+    fun test_set_str do
+        op1.set_str("30".to_cstring, 10i32)
+        assert(op1.cmp_si(30) == 0)
+    end
+
+    fun test_swap do
+        op1.set_si 10
+        op2.set_si 20
+        op1.swap op2
+        assert(op1.cmp_si(20) == 0 and op2.cmp_si(10) == 0)
+    end
+
+    fun test_get_si do
+        op1.set_si 12
+        assert(op1.get_si == 12)
+    end
+
+    fun test_get_d do
+        op1.set_si 12
+        assert(op1.get_d == 12.0)
+    end
+
+    fun test_get_str do
+        op1.set_si 12
+        assert(op1.get_str(10i32).to_s == "12")
+    end
+end
+
+class TestNativeMPQ
+    super TestSuite
+
+    var op1: NativeMPQ
+    var op2: NativeMPQ
+    var l: NativeMPZ
+    var res: NativeMPQ
+
+    init do end
+
+    redef fun before_test do
+        op1 = new NativeMPQ
+        op2 = new NativeMPQ
+        l = new NativeMPZ
+        res = new NativeMPQ
+    end
+
+    redef fun after_test do
+        op1.finalize
+        op2.finalize
+        l.finalize
+        res.finalize
+    end
+
+    fun test_add do
+        op1.set_si(10, 3)
+        op2.set_si(20, 3)
+        op1.add(res, op2)
+        assert(res.cmp_si(10, 1) == 0)
+    end
+
+    fun test_sub do
+        op1.set_si(20, 3)
+        op2.set_si(10, 3)
+        op1.sub(res, op2)
+        assert(res.cmp_si(10, 3) == 0)
+    end
+
+    fun test_mul do
+        op1.set_si(10, 3)
+        op2.set_si(10, 1)
+        op1.mul(res, op2)
+        assert(res.cmp_si(100, 3) == 0)
+    end
+
+    fun test_div do
+        op1.set_si(10, 3)
+        op2.set_si(2, 1)
+        op1.div(res, op2)
+        assert(res.cmp_si(5, 3) == 0)
+    end
+
+    fun test_neg do
+        op1.set_si(10, 3)
+        op1.neg(res)
+        assert(res.cmp_si(-10, 3) == 0)
+    end
+
+    fun test_abs do
+        op1.set_si(-10, 3)
+        op1.abs(res)
+        assert(res.cmp_si(10, 3) == 0)
+    end
+
+    fun test_inv do
+        op1.set_si(10, 3)
+        op1.inv(res)
+        assert(res.cmp_si(3, 10) == 0)
+    end
+
+    fun test_set do
+        op1.set_si(10, 3)
+        res.set op1
+        assert(res.cmp(op1) == 0)
+    end
+
+    fun test_set_z do
+        l.set_si 10
+        res.set_z l
+        assert(res.cmp_si(10, 1) == 0)
+    end
+
+    fun test_set_si do
+        res.set_si(10, 3)
+        assert(res.cmp_si(10, 3) == 0)
+    end
+
+    fun test_set_d do
+        res.set_d(0.5)
+        assert(res.cmp_si(1, 2) == 0)
+    end
+
+    fun test_set_str do
+        res.set_str "1/2".to_cstring
+        assert(res.cmp_si(1, 2) == 0)
+    end
+
+    fun test_swap do
+        op1.set_si(10, 3)
+        res.swap(op1)
+        assert(res.cmp_si(10, 3) == 0)
+    end
+
+    fun test_get_d do
+        res.set_si(1, 2)
+        assert(res.get_d == 0.5)
+    end
+
+    fun test_get_str do
+        res.set_si(1, 2)
+        assert(res.get_str(10i32).to_s == "1/2")
+    end
+
+    fun test_cmp do
+        op1.set_si(10, 3)
+        op2.set_si(10, 3)
+        assert(op1.cmp(op2) == 0)
+    end
+
+#    fun test_cmp_z do
+#        op1.set_si(10, 1)
+#        l.set_si 10
+#        assert(op1.cmp_z(l) == 0)
+#    end
+
+    fun test_cmp_si do
+        op1.set_si(10, 3)
+        assert(op1.cmp_si(10, 3) == 0)
+    end
+
+    fun test_equal do
+        op1.set_si(10, 3)
+        op2.set_si(10, 3)
+        assert op1.equal(op2)
+    end
+
+    fun test_numref do
+        op1.set_si(10, 3)
+        l.set_si 10
+        assert(op1.numref.cmp(l) == 0)
+    end
+
+    fun test_denref do
+        op1.set_si(10, 3)
+        l.set_si 3
+        assert(op1.denref.cmp(l) == 0)
+    end
+end