You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1353 lines
32 KiB
1353 lines
32 KiB
#include <stdio.h>
|
|
#include <mcl/vint.hpp>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <set>
|
|
#include <cybozu/benchmark.hpp>
|
|
#include <cybozu/test.hpp>
|
|
#include <cybozu/xorshift.hpp>
|
|
#ifndef DONT_USE_GMP_IN_TEST
|
|
#include <gmpxx.h>
|
|
#endif
|
|
|
|
#define PUT(x) std::cout << #x "=" << x << std::endl;
|
|
|
|
#if defined(__EMSCRIPTEN__) && !defined(MCL_AVOID_EXCEPTION_TEST)
|
|
#define MCL_AVOID_EXCEPTION_TEST
|
|
#endif
|
|
|
|
using namespace mcl;
|
|
|
|
struct V {
|
|
int n;
|
|
unsigned int p[16];
|
|
};
|
|
|
|
CYBOZU_TEST_AUTO(addSub)
|
|
{
|
|
static const struct {
|
|
V a;
|
|
V b;
|
|
V c;
|
|
} tbl[] = {
|
|
{
|
|
{ 1, { 123, } },
|
|
{ 1, { 456, } },
|
|
{ 1, { 579, } },
|
|
},
|
|
{
|
|
{ 1, { 0xffffffff, } },
|
|
{ 1, { 3, } },
|
|
{ 2, { 2, 1 } },
|
|
},
|
|
{
|
|
{ 3, { 0xffffffff, 1, 0xffffffff } },
|
|
{ 2, { 1, 0xfffffffe, } },
|
|
{ 4, { 0, 0, 0, 1 } },
|
|
},
|
|
{
|
|
{ 3, { 0xffffffff, 5, 0xffffffff } },
|
|
{ 2, { 1, 0xfffffffe, } },
|
|
{ 4, { 0, 4, 0, 1 } },
|
|
},
|
|
{
|
|
{ 3, { 0xffffffff, 5, 0xffffffff } },
|
|
{ 1, { 1, } },
|
|
{ 3, { 0, 6, 0xffffffff } },
|
|
},
|
|
{
|
|
{ 3, { 1, 0xffffffff, 1 } },
|
|
{ 3, { 0xffffffff, 0, 1 } },
|
|
{ 3, { 0, 0, 3 } },
|
|
},
|
|
{
|
|
{ 1, { 1 } },
|
|
{ 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
|
|
{ 4, { 0, 0, 0, 1 } },
|
|
},
|
|
{
|
|
{ 1, { 0xffffffff } },
|
|
{ 1, { 0xffffffff } },
|
|
{ 2, { 0xfffffffe, 1 } },
|
|
},
|
|
{
|
|
{ 2, { 0xffffffff, 0xffffffff } },
|
|
{ 2, { 0xffffffff, 0xffffffff } },
|
|
{ 3, { 0xfffffffe, 0xffffffff, 1 } },
|
|
},
|
|
{
|
|
{ 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
|
|
{ 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
|
|
{ 4, { 0xfffffffe, 0xffffffff, 0xffffffff, 1 } },
|
|
},
|
|
{
|
|
{ 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
|
|
{ 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
|
|
{ 5, { 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 1 } },
|
|
},
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
Vint x, y, z, t;
|
|
x.setArray(tbl[i].a.p, tbl[i].a.n);
|
|
y.setArray(tbl[i].b.p, tbl[i].b.n);
|
|
z.setArray(tbl[i].c.p, tbl[i].c.n);
|
|
Vint::add(t, x, y);
|
|
CYBOZU_TEST_EQUAL(t, z);
|
|
|
|
Vint::add(t, y, x);
|
|
CYBOZU_TEST_EQUAL(t, z);
|
|
|
|
Vint::sub(t, z, x);
|
|
CYBOZU_TEST_EQUAL(t, y);
|
|
}
|
|
{
|
|
const uint32_t in[] = { 0xffffffff, 0xffffffff };
|
|
const uint32_t out[] = { 0xfffffffe, 0xffffffff, 1 };
|
|
Vint x, y;
|
|
x.setArray(in, 2);
|
|
y.setArray(out, 3);
|
|
Vint::add(x, x, x);
|
|
CYBOZU_TEST_EQUAL(x, y);
|
|
Vint::sub(x, x, x);
|
|
y.clear();
|
|
CYBOZU_TEST_EQUAL(x, y);
|
|
}
|
|
{
|
|
const uint32_t t0[] = {1, 2};
|
|
const uint32_t t1[] = {3, 4, 5};
|
|
const uint32_t t2[] = {4, 6, 5};
|
|
Vint x, y, z;
|
|
z.setArray(t2, 3);
|
|
|
|
x.setArray(t0, 2);
|
|
y.setArray(t1, 3);
|
|
Vint::add(x, x, y);
|
|
CYBOZU_TEST_EQUAL(x, z);
|
|
|
|
x.setArray(t0, 2);
|
|
y.setArray(t1, 3);
|
|
Vint::add(x, y, x);
|
|
CYBOZU_TEST_EQUAL(x, z);
|
|
|
|
x.setArray(t0, 2);
|
|
y.setArray(t1, 3);
|
|
Vint::add(y, x, y);
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
|
|
x.setArray(t0, 2);
|
|
y.setArray(t1, 3);
|
|
Vint::add(y, y, x);
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(mul1)
|
|
{
|
|
static const struct {
|
|
V a;
|
|
int b;
|
|
V c;
|
|
} tbl[] = {
|
|
{
|
|
{ 1, { 12, } },
|
|
5,
|
|
{ 1, { 60, } },
|
|
},
|
|
{
|
|
{ 1, { 1234567, } },
|
|
1,
|
|
{ 1, { 1234567, } },
|
|
},
|
|
{
|
|
{ 1, { 1234567, } },
|
|
89012345,
|
|
{ 2, { 0x27F6EDCF, 0x63F2, } },
|
|
},
|
|
{
|
|
{ 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
|
|
0x7fffffff,
|
|
{ 4, { 0x80000001, 0xffffffff, 0xffffffff, 0x7ffffffe } },
|
|
},
|
|
{
|
|
{ 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
|
|
1,
|
|
{ 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
|
|
},
|
|
{
|
|
{ 2, { 0xffffffff, 1 } },
|
|
0x7fffffff,
|
|
{ 2, { 0x80000001, 0xfffffffd } },
|
|
},
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
Vint x, z, t;
|
|
int y;
|
|
x.setArray(tbl[i].a.p, tbl[i].a.n);
|
|
y = tbl[i].b;
|
|
z.setArray(tbl[i].c.p, tbl[i].c.n);
|
|
Vint::mul(t, x, y);
|
|
CYBOZU_TEST_EQUAL(t, z);
|
|
|
|
Vint::mul(x, x, y);
|
|
CYBOZU_TEST_EQUAL(x, z);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(mul2)
|
|
{
|
|
static const struct {
|
|
V a;
|
|
V b;
|
|
V c;
|
|
} tbl[] = {
|
|
{
|
|
{ 1, { 12, } },
|
|
{ 1, { 5, } },
|
|
{ 1, { 60, } },
|
|
},
|
|
{
|
|
{ 1, { 1234567, } },
|
|
{ 1, { 89012345, } },
|
|
{ 2, { 0x27F6EDCF, 0x63F2, } },
|
|
},
|
|
{
|
|
{ 3, { 0xffffffff, 0xffffffff, 0xffffffff, } },
|
|
{ 1, { 0xffffffff, } },
|
|
{ 4, { 0x00000001, 0xffffffff, 0xffffffff, 0xfffffffe } },
|
|
},
|
|
{
|
|
{ 2, { 0xffffffff, 1 } },
|
|
{ 1, { 0xffffffff, } },
|
|
{ 3, { 0x00000001, 0xfffffffd, 1 } },
|
|
},
|
|
{
|
|
{ 2, { 0xffffffff, 1 } },
|
|
{ 1, { 0xffffffff, } },
|
|
{ 3, { 0x00000001, 0xfffffffd, 1 } },
|
|
},
|
|
{
|
|
{ 2, { 1, 1 } },
|
|
{ 2, { 1, 1 } },
|
|
{ 3, { 1, 2, 1 } },
|
|
},
|
|
{
|
|
{ 3, { 0xffffffff, 0xffffffff, 1 } },
|
|
{ 2, { 0xffffffff, 0xffffffff } },
|
|
{ 5, { 1, 0, 0xfffffffd, 0xffffffff, 1 } },
|
|
},
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
Vint x, y, z, t;
|
|
x.setArray(tbl[i].a.p, tbl[i].a.n);
|
|
y.setArray(tbl[i].b.p, tbl[i].b.n);
|
|
z.setArray(tbl[i].c.p, tbl[i].c.n);
|
|
Vint::mul(t, x, y);
|
|
CYBOZU_TEST_EQUAL(t, z);
|
|
|
|
Vint::mul(t, y, x);
|
|
CYBOZU_TEST_EQUAL(t, z);
|
|
}
|
|
{
|
|
const uint32_t in[] = { 0xffffffff, 1 };
|
|
const uint32_t out[] = { 1, 0xfffffffc, 3 };
|
|
Vint x, y, z;
|
|
y.setArray(out, 3);
|
|
x.setArray(in, 2);
|
|
z = x;
|
|
Vint::mul(x, x, x);
|
|
CYBOZU_TEST_EQUAL(x, y);
|
|
|
|
x.setArray(in, 2);
|
|
Vint::mul(x, x, z);
|
|
CYBOZU_TEST_EQUAL(x, y);
|
|
|
|
x.setArray(in, 2);
|
|
Vint::mul(x, z, x);
|
|
CYBOZU_TEST_EQUAL(x, y);
|
|
|
|
x.setArray(in, 2);
|
|
Vint::mul(x, z, z);
|
|
CYBOZU_TEST_EQUAL(x, y);
|
|
}
|
|
{
|
|
Vint a("285434247217355341057");
|
|
a *= a;
|
|
CYBOZU_TEST_EQUAL(a, Vint("81472709484538325259309302444004789877249"));
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(div1)
|
|
{
|
|
static const struct {
|
|
V a;
|
|
unsigned int b;
|
|
unsigned int r;
|
|
V c;
|
|
} tbl[] = {
|
|
{
|
|
{ 1, { 100, } },
|
|
1, 0,
|
|
{ 1, { 100, } },
|
|
},
|
|
{
|
|
{ 1, { 100, } },
|
|
100, 0,
|
|
{ 1, { 1, } },
|
|
},
|
|
{
|
|
{ 1, { 100, } },
|
|
101, 100,
|
|
{ 1, { 0, } },
|
|
},
|
|
{
|
|
{ 1, { 100, } },
|
|
2, 0,
|
|
{ 1, { 50, } },
|
|
},
|
|
{
|
|
{ 1, { 100, } },
|
|
3, 1,
|
|
{ 1, { 33, } },
|
|
},
|
|
{
|
|
{ 2, { 0xffffffff, 0xffffffff } },
|
|
1, 0,
|
|
{ 2, { 0xffffffff, 0xffffffff, } },
|
|
},
|
|
{
|
|
{ 2, { 0xffffffff, 0xffffffff } },
|
|
123, 15,
|
|
{ 2, { 0x4d0214d0, 0x214d021 } },
|
|
},
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
Vint x, z, t;
|
|
unsigned int b, r, u;
|
|
x.setArray(tbl[i].a.p, tbl[i].a.n);
|
|
b = tbl[i].b;
|
|
r = tbl[i].r;
|
|
z.setArray(tbl[i].c.p, tbl[i].c.n);
|
|
|
|
u = (unsigned int)Vint::divMods1(&t, x, b);
|
|
CYBOZU_TEST_EQUAL(t, z);
|
|
CYBOZU_TEST_EQUAL(u, r);
|
|
|
|
u = (unsigned int)Vint::divMods1(&x, x, b);
|
|
CYBOZU_TEST_EQUAL(x, z);
|
|
CYBOZU_TEST_EQUAL(u, r);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(div2)
|
|
{
|
|
static const struct {
|
|
V x;
|
|
V y;
|
|
V q;
|
|
V r;
|
|
} tbl[] = {
|
|
{
|
|
{ 1, { 100 } },
|
|
{ 1, { 3 } },
|
|
{ 1, { 33 } },
|
|
{ 1, { 1 } },
|
|
},
|
|
{
|
|
{ 2, { 1, 1 } },
|
|
{ 2, { 0, 1 } },
|
|
{ 1, { 1 } },
|
|
{ 1, { 1 } },
|
|
},
|
|
{
|
|
{ 2, { 0xffffffff, 0xffffffff } },
|
|
{ 2, { 0, 1 } },
|
|
{ 1, { 0xffffffff } },
|
|
{ 1, { 0xffffffff } },
|
|
},
|
|
{
|
|
{ 2, { 0xffffffff, 0xffffffff } },
|
|
{ 2, { 0xffffffff, 1 } },
|
|
{ 1, { 0x80000000 } },
|
|
{ 1, { 0x7fffffff } },
|
|
},
|
|
{
|
|
{ 3, { 0xffffffff, 0xffffffff, 0xffffffff } },
|
|
{ 2, { 0xffffffff, 1 } },
|
|
{ 2, { 0x40000000, 0x80000000 } },
|
|
{ 1, { 0x3fffffff } },
|
|
},
|
|
{
|
|
{ 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
|
|
{ 3, { 1, 0, 1 } },
|
|
{ 2, { 0xffffffff, 0xffffffff } },
|
|
{ 1, { 0 } },
|
|
},
|
|
{
|
|
{ 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
|
|
{ 3, { 1, 0xffffffff, 0xffffffff } },
|
|
{ 2, { 0, 1 } },
|
|
{ 2, { 0xffffffff, 0xfffffffe } },
|
|
},
|
|
{
|
|
{ 4, { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff } },
|
|
{ 3, { 1, 0, 0xffffffff } },
|
|
{ 2, { 1, 1 } },
|
|
{ 2, { 0xfffffffe, 0xfffffffe } },
|
|
},
|
|
{
|
|
{ 4, { 0xffffffff, 0xffffffff, 0xffffffff, 1 } },
|
|
{ 3, { 1, 0, 0xffffffff } },
|
|
{ 1, { 2 } },
|
|
{ 3, { 0xfffffffd, 0xffffffff, 1 } },
|
|
},
|
|
{
|
|
{ 4, { 0, 0, 1, 1 } },
|
|
{ 2, { 1, 1 } },
|
|
{ 3, { 0, 0, 1 } },
|
|
{ 1, { 0 } },
|
|
},
|
|
{
|
|
{ 3, { 5, 5, 1} },
|
|
{ 2, { 1, 2 } },
|
|
{ 1, { 0x80000002 } },
|
|
{ 1, { 0x80000003, } },
|
|
},
|
|
{
|
|
{ 2, { 5, 5} },
|
|
{ 2, { 1, 1 } },
|
|
{ 1, { 5 } },
|
|
{ 1, { 0, } },
|
|
},
|
|
{
|
|
{ 2, { 5, 5} },
|
|
{ 2, { 2, 1 } },
|
|
{ 1, { 4 } },
|
|
{ 1, { 0xfffffffd, } },
|
|
},
|
|
{
|
|
{ 3, { 5, 0, 5} },
|
|
{ 3, { 2, 0, 1 } },
|
|
{ 1, { 4 } },
|
|
{ 2, { 0xfffffffd, 0xffffffff } },
|
|
},
|
|
{
|
|
{ 2, { 4, 5 } },
|
|
{ 2, { 5, 5 } },
|
|
{ 1, { 0 } },
|
|
{ 2, { 4, 5 } },
|
|
},
|
|
{
|
|
{ 1, { 123 } },
|
|
{ 2, { 1, 1 } },
|
|
{ 1, { 0 } },
|
|
{ 1, { 123 } },
|
|
},
|
|
{
|
|
{ 1, { 123 } },
|
|
{ 3, { 1, 1, 1 } },
|
|
{ 1, { 0 } },
|
|
{ 1, { 123 } },
|
|
},
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
Vint x, y, q, r;
|
|
x.setArray(tbl[i].x.p, tbl[i].x.n);
|
|
y.setArray(tbl[i].y.p, tbl[i].y.n);
|
|
q.setArray(tbl[i].q.p, tbl[i].q.n);
|
|
r.setArray(tbl[i].r.p, tbl[i].r.n);
|
|
|
|
Vint qt, rt;
|
|
Vint::quotRem(&qt, rt, x, y);
|
|
CYBOZU_TEST_EQUAL(qt, q);
|
|
CYBOZU_TEST_EQUAL(rt, r);
|
|
|
|
Vint::mul(y, y, qt);
|
|
Vint::add(y, y, rt);
|
|
CYBOZU_TEST_EQUAL(x, y);
|
|
|
|
x.setArray(tbl[i].x.p, tbl[i].x.n);
|
|
y.setArray(tbl[i].y.p, tbl[i].y.n);
|
|
Vint::quotRem(&x, rt, x, y);
|
|
CYBOZU_TEST_EQUAL(x, q);
|
|
CYBOZU_TEST_EQUAL(rt, r);
|
|
|
|
x.setArray(tbl[i].x.p, tbl[i].x.n);
|
|
y.setArray(tbl[i].y.p, tbl[i].y.n);
|
|
Vint::quotRem(&y, rt, x, y);
|
|
CYBOZU_TEST_EQUAL(y, q);
|
|
CYBOZU_TEST_EQUAL(rt, r);
|
|
|
|
x.setArray(tbl[i].x.p, tbl[i].x.n);
|
|
y.setArray(tbl[i].y.p, tbl[i].y.n);
|
|
Vint::quotRem(&x, y, x, y);
|
|
CYBOZU_TEST_EQUAL(x, q);
|
|
CYBOZU_TEST_EQUAL(y, r);
|
|
|
|
x.setArray(tbl[i].x.p, tbl[i].x.n);
|
|
y.setArray(tbl[i].y.p, tbl[i].y.n);
|
|
Vint::quotRem(&y, x, x, y);
|
|
CYBOZU_TEST_EQUAL(y, q);
|
|
CYBOZU_TEST_EQUAL(x, r);
|
|
}
|
|
{
|
|
const uint32_t in[] = { 1, 1 };
|
|
Vint x, y, z;
|
|
x.setArray(in, 2);
|
|
Vint::quotRem(&x, y, x, x);
|
|
z = 1;
|
|
CYBOZU_TEST_EQUAL(x, z);
|
|
z.clear();
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
|
|
Vint::quotRem(&y, x, x, x);
|
|
z = 1;
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
z.clear();
|
|
CYBOZU_TEST_EQUAL(x, z);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(quotRem)
|
|
{
|
|
const struct {
|
|
const char *x;
|
|
const char *y;
|
|
const char *r;
|
|
} tbl[] = {
|
|
{
|
|
"1448106640508192452750709206294683535529268965445799785581837640324321797831381715960812126274894517677713278300997728292641936248881345120394299128611830",
|
|
"82434016654300679721217353503190038836571781811386228921167322412819029493183",
|
|
"72416512377294697540770834088766459385112079195086911762075702918882982361282"
|
|
},
|
|
{
|
|
"97086308670107713719105336221824613370040805954034005192338040686500414395543303807941158656814978071549225072789349941064484974666540443679601226744652",
|
|
"82434016654300679721217353503190038836571781811386228921167322412819029493183",
|
|
"41854959563040430269871677548536437787164514279279911478858426970427834388586",
|
|
},
|
|
{
|
|
"726838724295606887174238120788791626017347752989142414466410919788841485181240131619880050064495352797213258935807786970844241989010252",
|
|
"82434016654300679721217353503190038836571781811386228921167322412819029493183",
|
|
"81378967132566843036693176764684783485107373533583677681931133755003929106966",
|
|
},
|
|
{
|
|
"85319207237201203511459960875801690195851794174784746933408178697267695525099750",
|
|
"82434016654300679721217353503190038836571781811386228921167322412819029493183",
|
|
"82434016654300679721217353503190038836571781811386228921167322412819029148528",
|
|
},
|
|
{
|
|
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
"0x100000000000000000000000000000000000000000000000001",
|
|
"1606938044258990275541962092341162602522202993782724115824640",
|
|
},
|
|
{
|
|
"0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
"0x1000000000000000000000000000000000000000000000000000000000000000000000000000000001",
|
|
"34175792574734561318320347298712833833643272357332299899995954578095372295314880347335474659983360",
|
|
},
|
|
{
|
|
"0xfffffffffffff000000000000000000000000000000000000000000000000000000000000000000",
|
|
"0x100000000000000000000000000000000000000000000000000000000000000000001",
|
|
"7558907585412001237250713901367146624661464598973016020495791084036551510708977665",
|
|
},
|
|
{
|
|
"0xfffffffffffff000000000000000000000000000000000000000000000000000000000000000000",
|
|
"0xfffffffffffff0000000000000000000000000000000000000000000000000000000000000001",
|
|
"521481209941628322292632858916605385658190900090571826892867289394157573281830188869820088065",
|
|
},
|
|
{
|
|
"0x1230000000000000456",
|
|
"0x1230000000000000457",
|
|
"0x1230000000000000456",
|
|
},
|
|
{
|
|
"0x1230000000000000456",
|
|
"0x1230000000000000456",
|
|
"0",
|
|
},
|
|
{
|
|
"0x1230000000000000456",
|
|
"0x1230000000000000455",
|
|
"1",
|
|
},
|
|
{
|
|
"0x1230000000000000456",
|
|
"0x2000000000000000000",
|
|
"0x1230000000000000456",
|
|
},
|
|
{
|
|
"0xffffffffffffffffffffffffffffffff",
|
|
"0x80000000000000000000000000000000",
|
|
"0x7fffffffffffffffffffffffffffffff",
|
|
},
|
|
{
|
|
"0xffffffffffffffffffffffffffffffff",
|
|
"0x7fffffffffffffffffffffffffffffff",
|
|
"1",
|
|
},
|
|
{
|
|
"0xffffffffffffffffffffffffffffffff",
|
|
"0x70000000000000000000000000000000",
|
|
"0x1fffffffffffffffffffffffffffffff",
|
|
},
|
|
{
|
|
"0xffffffffffffffffffffffffffffffff",
|
|
"0x30000000000000000000000000000000",
|
|
"0x0fffffffffffffffffffffffffffffff",
|
|
},
|
|
{
|
|
"0xffffffffffffffffffffffffffffffff",
|
|
"0x10000000000000000000000000000000",
|
|
"0x0fffffffffffffffffffffffffffffff",
|
|
},
|
|
{
|
|
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
"0x2523648240000001ba344d80000000086121000000000013a700000000000013",
|
|
"0x212ba4f27ffffff5a2c62effffffffcdb939ffffffffff8a15ffffffffffff8d",
|
|
},
|
|
{
|
|
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
"0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d",
|
|
"0x212ba4f27ffffff5a2c62effffffffd00242ffffffffff9c39ffffffffffffb1",
|
|
},
|
|
};
|
|
mcl::Vint x, y, q, r1, r2;
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
x.setStr(tbl[i].x);
|
|
y.setStr(tbl[i].y);
|
|
r1.setStr(tbl[i].r);
|
|
mcl::Vint::divMod(&q, r2, x, y);
|
|
CYBOZU_TEST_EQUAL(r1, r2);
|
|
CYBOZU_TEST_EQUAL(x, q * y + r2);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(string)
|
|
{
|
|
const struct {
|
|
uint32_t v[5];
|
|
size_t vn;
|
|
const char *str;
|
|
const char *hex;
|
|
const char *bin;
|
|
} tbl[] = {
|
|
{ { 0 }, 0, "0", "0x0", "0b0" },
|
|
{ { 12345 }, 1, "12345", "0x3039", "0b11000000111001" },
|
|
{ { 0xffffffff }, 1, "4294967295", "0xffffffff", "0b11111111111111111111111111111111" },
|
|
{ { 0, 1 }, 2, "4294967296", "0x100000000", "0b100000000000000000000000000000000" },
|
|
{ { 0, 0, 0, 0, 1 }, 5, "340282366920938463463374607431768211456", "0x100000000000000000000000000000000", "0b100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" },
|
|
{ { 0, 0x0b22a000, 0xe2f768a0, 0xe086b93c, 0x2cd76f }, 5, "1000000000000000000000000000000000000000000000", "0x2cd76fe086b93ce2f768a00b22a00000000000", "0b101100110101110110111111100000100001101011100100111100111000101111011101101000101000000000101100100010101000000000000000000000000000000000000000000000" },
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
Vint x, y;
|
|
x.setArray(tbl[i].v,tbl[i].vn);
|
|
CYBOZU_TEST_EQUAL(x.getStr(10), tbl[i].str);
|
|
char buf[1024];
|
|
size_t n = x.getStr(buf, sizeof(buf), 10);
|
|
CYBOZU_TEST_ASSERT(n > 0);
|
|
CYBOZU_TEST_EQUAL(tbl[i].str, buf);
|
|
y.setStr(tbl[i].str);
|
|
CYBOZU_TEST_EQUAL(x.getStr(16), tbl[i].hex + 2);
|
|
n = x.getStr(buf, sizeof(buf), 16);
|
|
CYBOZU_TEST_ASSERT(n > 0);
|
|
CYBOZU_TEST_EQUAL(tbl[i].hex + 2, buf);
|
|
CYBOZU_TEST_EQUAL(x, y);
|
|
x = 1;
|
|
x.setStr(tbl[i].hex);
|
|
CYBOZU_TEST_EQUAL(x, y);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(shift)
|
|
{
|
|
Vint x("123423424918471928374192874198274981274918274918274918243");
|
|
Vint y, z;
|
|
|
|
const size_t unitBitSize = Vint::unitBitSize;
|
|
Vint s;
|
|
// shl
|
|
for (size_t i = 1; i < 31; i++) {
|
|
Vint::shl(y, x, i);
|
|
z = x * (Vint::Unit(1) << i);
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
y = x << i;
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
y = x;
|
|
y <<= i;
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
}
|
|
for (int i = 0; i < 4; i++) {
|
|
Vint::shl(y, x, i * unitBitSize);
|
|
Vint::pow(s, Vint(2), i * unitBitSize);
|
|
z = x * s;
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
y = x << (i * unitBitSize);
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
y = x;
|
|
y <<= (i * unitBitSize);
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
}
|
|
for (int i = 0; i < 100; i++) {
|
|
y = x << i;
|
|
Vint::pow(s, Vint(2), i);
|
|
z = x * s;
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
y = x;
|
|
y <<= i;
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
}
|
|
|
|
// shr
|
|
for (size_t i = 1; i < 31; i++) {
|
|
Vint::shr(y, x, i);
|
|
z = x / (Vint::Unit(1) << i);
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
y = x >> i;
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
y = x;
|
|
y >>= i;
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
}
|
|
for (int i = 0; i < 3; i++) {
|
|
Vint::shr(y, x, i * unitBitSize);
|
|
Vint::pow(s, Vint(2), i * unitBitSize);
|
|
z = x / s;
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
y = x >> (i * unitBitSize);
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
y = x;
|
|
y >>= (i * unitBitSize);
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
}
|
|
for (int i = 0; i < 100; i++) {
|
|
y = x >> i;
|
|
Vint::pow(s, Vint(2), i);
|
|
z = x / s;
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
y = x;
|
|
y >>= i;
|
|
CYBOZU_TEST_EQUAL(y, z);
|
|
}
|
|
{
|
|
Vint a = 0, zero = 0;
|
|
a <<= Vint::unitBitSize;
|
|
CYBOZU_TEST_EQUAL(a, zero);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(getBitSize)
|
|
{
|
|
{
|
|
Vint zero = 0;
|
|
CYBOZU_TEST_EQUAL(zero.getBitSize(), 1);
|
|
zero <<= (Vint::unitBitSize - 1);
|
|
CYBOZU_TEST_EQUAL(zero.getBitSize(), 1);
|
|
zero <<= Vint::unitBitSize;
|
|
CYBOZU_TEST_EQUAL(zero.getBitSize(), 1);
|
|
}
|
|
|
|
{
|
|
Vint a = 1;
|
|
CYBOZU_TEST_EQUAL(a.getBitSize(), 1);
|
|
a = 2;
|
|
CYBOZU_TEST_EQUAL(a.getBitSize(), 2);
|
|
a = 3;
|
|
CYBOZU_TEST_EQUAL(a.getBitSize(), 2);
|
|
a = 4;
|
|
CYBOZU_TEST_EQUAL(a.getBitSize(), 3);
|
|
}
|
|
|
|
{
|
|
Vint a = 5;
|
|
const size_t msbindex = a.getBitSize();
|
|
const size_t width = 100;
|
|
const size_t time = 3;
|
|
for (size_t i = 0; i < time; ++i) {
|
|
a <<= width;
|
|
CYBOZU_TEST_EQUAL(a.getBitSize(), msbindex + width*(i + 1));
|
|
}
|
|
|
|
for (size_t i = 0; i < time*2; ++i) {
|
|
a >>= width/2;
|
|
CYBOZU_TEST_EQUAL(a.getBitSize(), msbindex + width*time - (width/2)*(i + 1));
|
|
}
|
|
a >>= width;
|
|
CYBOZU_TEST_ASSERT(a.isZero());
|
|
CYBOZU_TEST_EQUAL(a.getBitSize(), 1);
|
|
}
|
|
|
|
{
|
|
Vint b("12"), c("345"), d("67890");
|
|
size_t bl = b.getBitSize(), cl = c.getBitSize(), dl = d.getBitSize();
|
|
CYBOZU_TEST_ASSERT((b*c).getBitSize() <= bl + cl);
|
|
CYBOZU_TEST_ASSERT((c*d).getBitSize() <= cl + dl);
|
|
CYBOZU_TEST_ASSERT((b*c*d).getBitSize() <= bl + cl + dl);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(bit)
|
|
{
|
|
Vint a;
|
|
a.setStr("0x1234567890abcdef");
|
|
bool tvec[] = {
|
|
1,1,1,1,0 ,1,1,1,1,0
|
|
,1,1,0,0,1 ,1,1,1,0,1
|
|
,0,1,0,1,0 ,0,0,0,1,0
|
|
,0,1,0,0,0 ,1,1,1,1,0
|
|
,0,1,1,0,1 ,0,1,0,0,0
|
|
,1,0,1,1,0 ,0,0,1,0,0
|
|
,1
|
|
};
|
|
CYBOZU_TEST_EQUAL(a.getBitSize(), sizeof(tvec)/sizeof(*tvec));
|
|
for (int i = (int)a.getBitSize() - 1; i >= 0; --i) {
|
|
CYBOZU_TEST_EQUAL(a.testBit(i), tvec[i]);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(sample)
|
|
{
|
|
using namespace mcl;
|
|
Vint x(1);
|
|
Vint y("123456789");
|
|
Vint z;
|
|
|
|
x = 1; // set by int
|
|
y.setStr("123456789"); // set by decimal
|
|
z.setStr("0xffffffff"); // set by hex
|
|
x += z;
|
|
|
|
x = 2;
|
|
y = 250;
|
|
Vint::pow(x, x, y);
|
|
Vint r, q;
|
|
r = x % y;
|
|
q = x / y;
|
|
CYBOZU_TEST_EQUAL(q * y + r, x);
|
|
|
|
Vint::quotRem(&q, r, x, y); // get both r and q
|
|
CYBOZU_TEST_EQUAL(q * y + r, x);
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(Vint)
|
|
{
|
|
const struct {
|
|
int a;
|
|
int b;
|
|
/*
|
|
q, r ; like C
|
|
q2, r2 ; like Python
|
|
*/
|
|
int add, sub, mul, q, r, q2, r2;
|
|
} tbl[] = {
|
|
{ 13, 5, 18, 8, 65, 2, 3, 2, 3 },
|
|
{ 13, -5, 8, 18, -65, -2, 3, -3, -2 },
|
|
{ -13, 5, -8, -18, -65, -2, -3, -3, 2 },
|
|
{ -13, -5, -18, -8, 65, 2, -3, 2, -3 },
|
|
{ 5, 13, 18, -8, 65, 0, 5 , 0, 5},
|
|
{ 5, -13, -8, 18, -65, 0, 5 , -1, -8},
|
|
{ -5, 13, 8, -18, -65, 0, -5 , -1, 8},
|
|
{ -5, -13, -18, 8, 65, 0, -5 , 0, -5},
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
Vint a = tbl[i].a;
|
|
Vint b = tbl[i].b;
|
|
Vint add = a + b;
|
|
Vint sub = a - b;
|
|
Vint mul = a * b;
|
|
Vint q = a / b;
|
|
Vint r = a % b;
|
|
Vint q2, r2;
|
|
Vint::quotRem(&q2, r2, a, b);
|
|
CYBOZU_TEST_EQUAL(add, tbl[i].add);
|
|
CYBOZU_TEST_EQUAL(sub, tbl[i].sub);
|
|
CYBOZU_TEST_EQUAL(mul, tbl[i].mul);
|
|
CYBOZU_TEST_EQUAL(q, tbl[i].q);
|
|
CYBOZU_TEST_EQUAL(r, tbl[i].r);
|
|
CYBOZU_TEST_EQUAL(q * b + r, a);
|
|
CYBOZU_TEST_EQUAL(q2, tbl[i].q2);
|
|
CYBOZU_TEST_EQUAL(r2, tbl[i].r2);
|
|
CYBOZU_TEST_EQUAL(q2 * b + r2, a);
|
|
}
|
|
CYBOZU_TEST_EQUAL(Vint("15") / Vint("3"), Vint("5"));
|
|
CYBOZU_TEST_EQUAL(Vint("15") / Vint("-3"), Vint("-5"));
|
|
CYBOZU_TEST_EQUAL(Vint("-15") / Vint("3"), Vint("-5"));
|
|
CYBOZU_TEST_EQUAL(Vint("-15") / Vint("-3"), Vint("5"));
|
|
|
|
CYBOZU_TEST_EQUAL(Vint("15") % Vint("3"), Vint("0"));
|
|
CYBOZU_TEST_EQUAL(Vint("15") % Vint("-3"), Vint("0"));
|
|
CYBOZU_TEST_EQUAL(Vint("-15") % Vint("3"), Vint("0"));
|
|
CYBOZU_TEST_EQUAL(Vint("-15") % Vint("-3"), Vint("0"));
|
|
|
|
CYBOZU_TEST_EQUAL(Vint("-0") + Vint("-3"), Vint("-3"));
|
|
CYBOZU_TEST_EQUAL(Vint("-0") - Vint("-3"), Vint("3"));
|
|
CYBOZU_TEST_EQUAL(Vint("-3") + Vint("-0"), Vint("-3"));
|
|
CYBOZU_TEST_EQUAL(Vint("-3") - Vint("-0"), Vint("-3"));
|
|
|
|
CYBOZU_TEST_EQUAL(Vint("-0") + Vint("3"), Vint("3"));
|
|
CYBOZU_TEST_EQUAL(Vint("-0") - Vint("3"), Vint("-3"));
|
|
CYBOZU_TEST_EQUAL(Vint("3") + Vint("-0"), Vint("3"));
|
|
CYBOZU_TEST_EQUAL(Vint("3") - Vint("-0"), Vint("3"));
|
|
|
|
CYBOZU_TEST_EQUAL(Vint("0"), Vint("0"));
|
|
CYBOZU_TEST_EQUAL(Vint("0"), Vint("-0"));
|
|
CYBOZU_TEST_EQUAL(Vint("-0"), Vint("0"));
|
|
CYBOZU_TEST_EQUAL(Vint("-0"), Vint("-0"));
|
|
|
|
CYBOZU_TEST_ASSERT(Vint("2") < Vint("3"));
|
|
CYBOZU_TEST_ASSERT(Vint("-2") < Vint("3"));
|
|
CYBOZU_TEST_ASSERT(Vint("-5") < Vint("-3"));
|
|
CYBOZU_TEST_ASSERT(Vint("-0") < Vint("1"));
|
|
CYBOZU_TEST_ASSERT(Vint("-1") < Vint("-0"));
|
|
|
|
CYBOZU_TEST_ASSERT(Vint("5") > Vint("3"));
|
|
CYBOZU_TEST_ASSERT(Vint("5") > Vint("-3"));
|
|
CYBOZU_TEST_ASSERT(Vint("-2") > Vint("-3"));
|
|
CYBOZU_TEST_ASSERT(Vint("3") > Vint("-0"));
|
|
CYBOZU_TEST_ASSERT(Vint("-0") > Vint("-1"));
|
|
|
|
{
|
|
const struct {
|
|
const char *str;
|
|
int s;
|
|
int shl;
|
|
int shr;
|
|
} tbl2[] = {
|
|
{ "0", 1, 0, 0 },
|
|
{ "-0", 1, 0, 0 },
|
|
{ "1", 1, 2, 0 },
|
|
{ "-1", 1, -2, 0 },
|
|
{ "12345", 3, 98760, 1543 },
|
|
{ "-12345", 3, -98760, 0 },
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl2); i++) {
|
|
Vint a = Vint(tbl2[i].str);
|
|
Vint shl = a << tbl2[i].s;
|
|
CYBOZU_TEST_EQUAL(shl, tbl2[i].shl);
|
|
if (!a.isNegative()) {
|
|
Vint shr = a >> tbl2[i].s;
|
|
CYBOZU_TEST_EQUAL(shr, tbl2[i].shr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(add2)
|
|
{
|
|
Vint x, y, z, w;
|
|
x.setStr("2416089439321382744001761632872637936198961520379024187947524965775137204955564426500438089001375107581766516460437532995850581062940399321788596606850");
|
|
y.setStr("2416089439321382743300544243711595219403446085161565705825288050160594425031420687263897209379984490503106207071010949258995096347962762372787916800000");
|
|
z.setStr("701217389161042716795515435217458482122236915614542779924143739236540879621390617078660309389426583736855484714977636949000679806850");
|
|
Vint::sub(w, x, y);
|
|
CYBOZU_TEST_EQUAL(w, z);
|
|
|
|
Vint a, c, d;
|
|
|
|
a.setStr("-2416089439321382744001761632872637936198961520379024187947524965775137204955564426500438089001375107581766516460437532995850581062940399321788596606850");
|
|
c.setStr("2416089439321382743300544243711595219403446085161565705825288050160594425031420687263897209379984490503106207071010949258995096347962762372787916800000");
|
|
a = a + c;
|
|
|
|
d.setStr("-701217389161042716795515435217458482122236915614542779924143739236540879621390617078660309389426583736855484714977636949000679806850");
|
|
CYBOZU_TEST_EQUAL(a, d);
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(stream)
|
|
{
|
|
{
|
|
Vint x, y, z, w;
|
|
x.setStr("12345678901232342424242423423429922");
|
|
y.setStr("23423423452424242343");
|
|
std::ostringstream oss;
|
|
oss << x << ' ' << y;
|
|
std::istringstream iss(oss.str());
|
|
iss >> z >> w;
|
|
CYBOZU_TEST_EQUAL(x, z);
|
|
CYBOZU_TEST_EQUAL(y, w);
|
|
}
|
|
{
|
|
Vint x, y, z, w;
|
|
x.setStr("0x100");
|
|
y.setStr("123");
|
|
std::ostringstream oss;
|
|
oss << x << ' ' << y;
|
|
std::istringstream iss(oss.str());
|
|
iss >> z >> w;
|
|
CYBOZU_TEST_EQUAL(x, z);
|
|
CYBOZU_TEST_EQUAL(y, w);
|
|
}
|
|
{
|
|
Vint x, y, z, w;
|
|
x.setStr("12345678901232342424242423423429922");
|
|
y.setStr("-23423423452424242343");
|
|
std::ostringstream oss;
|
|
oss << x << ' ' << y;
|
|
std::istringstream iss(oss.str());
|
|
iss >> z >> w;
|
|
CYBOZU_TEST_EQUAL(x, z);
|
|
CYBOZU_TEST_EQUAL(y, w);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(inc_dec)
|
|
{
|
|
Vint x = 3;
|
|
CYBOZU_TEST_EQUAL(x++, 3);
|
|
CYBOZU_TEST_EQUAL(x, 4);
|
|
CYBOZU_TEST_EQUAL(++x, 5);
|
|
CYBOZU_TEST_EQUAL(x, 5);
|
|
|
|
CYBOZU_TEST_EQUAL(x--, 5);
|
|
CYBOZU_TEST_EQUAL(x, 4);
|
|
CYBOZU_TEST_EQUAL(--x, 3);
|
|
CYBOZU_TEST_EQUAL(x, 3);
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(withInt)
|
|
{
|
|
Vint x = 15;
|
|
x += 3;
|
|
CYBOZU_TEST_EQUAL(x, 18);
|
|
x -= 2;
|
|
CYBOZU_TEST_EQUAL(x, 16);
|
|
x *= 2;
|
|
CYBOZU_TEST_EQUAL(x, 32);
|
|
x /= 3;
|
|
CYBOZU_TEST_EQUAL(x, 10);
|
|
x = -x;
|
|
CYBOZU_TEST_EQUAL(x, -10);
|
|
x += 1;
|
|
CYBOZU_TEST_EQUAL(x, -9);
|
|
x -= 2;
|
|
CYBOZU_TEST_EQUAL(x, -11);
|
|
x *= 2;
|
|
CYBOZU_TEST_EQUAL(x, -22);
|
|
x /= 5;
|
|
CYBOZU_TEST_EQUAL(x, -4);
|
|
x = -22;
|
|
x %= 5;
|
|
CYBOZU_TEST_EQUAL(x, -2);
|
|
|
|
x = 3;
|
|
x += -2;
|
|
CYBOZU_TEST_EQUAL(x, 1);
|
|
x += -5;
|
|
CYBOZU_TEST_EQUAL(x, -4);
|
|
x -= -7;
|
|
CYBOZU_TEST_EQUAL(x, 3);
|
|
x *= -1;
|
|
CYBOZU_TEST_EQUAL(x, -3);
|
|
x /= -1;
|
|
CYBOZU_TEST_EQUAL(x, 3);
|
|
|
|
x++;
|
|
CYBOZU_TEST_EQUAL(x, 4);
|
|
x--;
|
|
CYBOZU_TEST_EQUAL(x, 3);
|
|
x = -3;
|
|
x++;
|
|
CYBOZU_TEST_EQUAL(x, -2);
|
|
x--;
|
|
CYBOZU_TEST_EQUAL(x, -3);
|
|
|
|
++x;
|
|
CYBOZU_TEST_EQUAL(x, -2);
|
|
--x;
|
|
CYBOZU_TEST_EQUAL(x, -3);
|
|
x = 3;
|
|
++x;
|
|
CYBOZU_TEST_EQUAL(x, 4);
|
|
--x;
|
|
CYBOZU_TEST_EQUAL(x, 3);
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(addu1)
|
|
{
|
|
Vint x = 4;
|
|
Vint::addu1(x, x, 2);
|
|
CYBOZU_TEST_EQUAL(x, 6);
|
|
Vint::subu1(x, x, 2);
|
|
CYBOZU_TEST_EQUAL(x, 4);
|
|
Vint::subu1(x, x, 10);
|
|
CYBOZU_TEST_EQUAL(x, -6);
|
|
x = -4;
|
|
Vint::addu1(x, x, 2);
|
|
CYBOZU_TEST_EQUAL(x, -2);
|
|
Vint::subu1(x, x, 2);
|
|
CYBOZU_TEST_EQUAL(x, -4);
|
|
Vint::addu1(x, x, 10);
|
|
CYBOZU_TEST_EQUAL(x, 6);
|
|
|
|
x.setStr("0x10000000000000000000000002");
|
|
Vint::subu1(x, x, 3);
|
|
CYBOZU_TEST_EQUAL(x, Vint("0xfffffffffffffffffffffffff"));
|
|
x.setStr("-0x10000000000000000000000000");
|
|
Vint::addu1(x, x, 5);
|
|
CYBOZU_TEST_EQUAL(x, Vint("-0xffffffffffffffffffffffffb"));
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(pow)
|
|
{
|
|
Vint x = 2;
|
|
Vint y;
|
|
Vint::pow(y, x, 3);
|
|
CYBOZU_TEST_EQUAL(y, 8);
|
|
x = -2;
|
|
Vint::pow(y, x, 3);
|
|
CYBOZU_TEST_EQUAL(y, -8);
|
|
#ifndef MCL_AVOID_EXCEPTION_TEST
|
|
// CYBOZU_TEST_EXCEPTION(Vint::pow(y, x, -2), cybozu::Exception);
|
|
#endif
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(powMod)
|
|
{
|
|
Vint x = 7;
|
|
Vint m = 65537;
|
|
Vint y;
|
|
Vint::powMod(y, x, 20, m);
|
|
CYBOZU_TEST_EQUAL(y, 55277);
|
|
Vint::powMod(y, x, m - 1, m);
|
|
CYBOZU_TEST_EQUAL(y, 1);
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(andOr)
|
|
{
|
|
Vint x("1223480928420984209849242");
|
|
Vint y("29348220482094820948208420984209482048204289482");
|
|
Vint z;
|
|
z = x & y;
|
|
CYBOZU_TEST_EQUAL(z, Vint("1209221003550923564822922"));
|
|
z = x | y;
|
|
CYBOZU_TEST_EQUAL(z, Vint("29348220482094820948208435244134352108849315802"));
|
|
#ifndef MCL_AVOID_EXCEPTION_TEST
|
|
// CYBOZU_TEST_EXCEPTION(Vint("-2") | Vint("5"), cybozu::Exception);
|
|
// CYBOZU_TEST_EXCEPTION(Vint("-2") & Vint("5"), cybozu::Exception);
|
|
#endif
|
|
x = 8;
|
|
x |= 7;
|
|
CYBOZU_TEST_EQUAL(x, 15);
|
|
x = 65536;
|
|
y = 8;
|
|
y &= x;
|
|
CYBOZU_TEST_EQUAL(y, 0);
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(invMod)
|
|
{
|
|
Vint m("100000000000000000039");
|
|
for (int i = 1; i < 100; i++) {
|
|
Vint x = i;
|
|
Vint y;
|
|
Vint::invMod(y, x, m);
|
|
CYBOZU_TEST_EQUAL((y * x) % m, 1);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(isPrime)
|
|
{
|
|
int primeTbl[] = {
|
|
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
|
|
67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137,
|
|
139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,197, 199, 211,
|
|
223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283,
|
|
293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379,
|
|
383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461,
|
|
463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563,
|
|
569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643,
|
|
647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739,
|
|
743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829,
|
|
839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937,
|
|
941, 947, 953, 967, 971, 977, 983, 991, 997
|
|
};
|
|
typedef std::set<int> IntSet;
|
|
IntSet primes;
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(primeTbl); i++) {
|
|
primes.insert(primeTbl[i]);
|
|
}
|
|
for (int i = 0; i < 1000; i++) {
|
|
bool ok = primes.find(i) != primes.end();
|
|
bool my = Vint(i).isPrime();
|
|
CYBOZU_TEST_EQUAL(ok, my);
|
|
}
|
|
const struct {
|
|
const char *n;
|
|
bool isPrime;
|
|
} tbl[] = {
|
|
{ "65537", true },
|
|
{ "449065", false },
|
|
{ "488881", false },
|
|
{ "512461", false },
|
|
{ "18446744073709551629", true },
|
|
{ "18446744073709551631", false },
|
|
{ "0x10000000000000000000000000000000000000007", true },
|
|
{ "0x10000000000000000000000000000000000000009", false },
|
|
{ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", true },
|
|
{ "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2d", false },
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
Vint x(tbl[i].n);
|
|
CYBOZU_TEST_EQUAL(x.isPrime(), tbl[i].isPrime);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(gcd)
|
|
{
|
|
Vint x = 12;
|
|
Vint y = 18;
|
|
Vint z;
|
|
Vint::gcd(z, x, y);
|
|
CYBOZU_TEST_EQUAL(z, 6);
|
|
Vint::lcm(z, x, y);
|
|
CYBOZU_TEST_EQUAL(z, 36);
|
|
Vint::lcm(x, x, y);
|
|
CYBOZU_TEST_EQUAL(x, 36);
|
|
Vint::lcm(x, x, x);
|
|
CYBOZU_TEST_EQUAL(x, 36);
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(jacobi)
|
|
{
|
|
const struct {
|
|
const char *m;
|
|
const char *n;
|
|
int ok;
|
|
} tbl[] = {
|
|
{ "0", "1", 1 },
|
|
{ "1", "1", 1 },
|
|
{ "123", "1", 1 },
|
|
{ "45", "77", -1 },
|
|
{ "60", "121", 1 },
|
|
{ "12345672342342342342428", "923423423424753211", 1 },
|
|
{ "12345672342342342342428","34592342234235424753211", -1 },
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
int my = Vint::jacobi(Vint(tbl[i].m), Vint(tbl[i].n));
|
|
CYBOZU_TEST_EQUAL(my, tbl[i].ok);
|
|
}
|
|
}
|
|
|
|
CYBOZU_TEST_AUTO(bench)
|
|
{
|
|
Vint x, y, z;
|
|
x.setStr("0x2523648240000001ba344d80000000086121000000000013a700000000000013");
|
|
y.setStr("0x1802938109810498104982094820498203942804928049284092424902424243");
|
|
|
|
int N = 100000;
|
|
CYBOZU_BENCH_C("add", N, Vint::add, z, x, y);
|
|
CYBOZU_BENCH_C("sub", N, Vint::sub, z, x, y);
|
|
CYBOZU_BENCH_C("mul", N, Vint::mul, z, x, y);
|
|
CYBOZU_BENCH_C("div", N, Vint::div, y, z, x);
|
|
|
|
const struct {
|
|
const char *x;
|
|
const char *y;
|
|
} tbl[] = {
|
|
{
|
|
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
"0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d"
|
|
},
|
|
{
|
|
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
"0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
|
|
},
|
|
{
|
|
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
|
"0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001",
|
|
},
|
|
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
x.setStr(tbl[i].x);
|
|
y.setStr(tbl[i].y);
|
|
CYBOZU_BENCH_C("fast div", N, Vint::div, z, x, y);
|
|
#ifndef DONT_USE_GMP_IN_TEST
|
|
{
|
|
mpz_class mx(tbl[i].x), my(tbl[i].y), mz;
|
|
CYBOZU_BENCH_C("gmp", N, mpz_div, mz.get_mpz_t(), mx.get_mpz_t(), my.get_mpz_t());
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
struct Seq {
|
|
const uint32_t *tbl;
|
|
size_t n;
|
|
size_t i, j;
|
|
Seq(const uint32_t *tbl, size_t n) : tbl(tbl), n(n), i(0), j(0) {}
|
|
bool next(uint64_t *v)
|
|
{
|
|
if (i == n) {
|
|
if (j == n - 1) return false;
|
|
i = 0;
|
|
j++;
|
|
}
|
|
*v = (uint64_t(tbl[j]) << 32) | tbl[i];
|
|
i++;
|
|
return true;
|
|
}
|
|
};
|
|
|
|
#if MCL_SIZEOF_UNIT == 8
|
|
CYBOZU_TEST_AUTO(divUnit)
|
|
{
|
|
const uint32_t tbl[] = {
|
|
0, 1, 3,
|
|
0x7fffffff,
|
|
0x80000000,
|
|
0x80000001,
|
|
0xffffffff,
|
|
};
|
|
const size_t n = sizeof(tbl) / sizeof(tbl[0]);
|
|
Seq seq3(tbl, n);
|
|
uint64_t y;
|
|
while (seq3.next(&y)) {
|
|
if (y == 0) continue;
|
|
Seq seq2(tbl, n);
|
|
uint64_t r;
|
|
while (seq2.next(&r)) {
|
|
if (r >= y) break;
|
|
Seq seq1(tbl, n);
|
|
uint64_t q;
|
|
while (seq1.next(&q)) {
|
|
uint64_t x[2];
|
|
x[0] = mcl::vint::mulUnit(&x[1], q, y);
|
|
mcl::vint::addu1(x, x, 2, r);
|
|
uint64_t Q, R;
|
|
//printf("q=0x%016llxull, r=0x%016llxull, y=0x%016llxull\n", (long long)q, (long long)r, (long long)y);
|
|
Q = mcl::vint::divUnit(&R, x[1], x[0], y);
|
|
CYBOZU_TEST_EQUAL(q, Q);
|
|
CYBOZU_TEST_EQUAL(r, R);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void compareMod(const uint64_t *x, const uint64_t *p)
|
|
{
|
|
uint64_t y1[4] = {};
|
|
uint64_t y2[4] = {};
|
|
mcl::vint::divNM((uint64_t*)0, 0, y1, x, 8, p, 4);
|
|
mcl::vint::mcl_fpDbl_mod_SECP256K1(y2, x, p);
|
|
CYBOZU_TEST_EQUAL_ARRAY(y1, y2, 4);
|
|
}
|
|
CYBOZU_TEST_AUTO(SECP256k1)
|
|
{
|
|
const uint64_t F = uint64_t(-1);
|
|
const uint64_t p[4] = { uint64_t(0xfffffffefffffc2full), F, F, F };
|
|
const uint64_t tbl[][8] = {
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
{ F, F, F, F, F, F, F, F },
|
|
{ F, F, F, F, 1, 0, 0, 0 },
|
|
};
|
|
for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(tbl); i++) {
|
|
const uint64_t *x = tbl[i];
|
|
compareMod(x, p);
|
|
}
|
|
cybozu::XorShift rg;
|
|
for (size_t i = 0; i < 100; i++) {
|
|
uint64_t x[8];
|
|
for (int j = 0; j < 8; j++) {
|
|
x[j] = rg();
|
|
}
|
|
compareMod(x, p);
|
|
}
|
|
}
|
|
#endif
|
|
|