From: PatrickBlanchette Date: Mon, 15 May 2017 13:56:46 +0000 (-0400) Subject: gmp: Introduce NativeMPZ and NativeMPQ with simple test X-Git-Url: http://nitlanguage.org?hp=d347abd62ec84f348276955eba867b48e6e5f29f gmp: Introduce NativeMPZ and NativeMPQ with simple test Signed-off-by: PatrickBlanchette --- diff --git a/lib/gmp/native_gmp.nit b/lib/gmp/native_gmp.nit new file mode 100644 index 0000000..8c8b86a --- /dev/null +++ b/lib/gmp/native_gmp.nit @@ -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 +`} + +# 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 index 0000000..b27a3c0 --- /dev/null +++ b/lib/gmp/test_native_gmp.nit @@ -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