aboutsummaryrefslogtreecommitdiffstats
path: root/include/mcl/fp_util.hpp
blob: 7712e9c2d015287b795f83c82714c6eac62a65b7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#pragma once
#include <vector>
#include <cybozu/itoa.hpp>
#include <cybozu/atoi.hpp>
#include <mcl/unit.hpp>
/**
    @file
    @brief utility of Fp
    @author MITSUNARI Shigeo(@herumi)
    @license modified new BSD license
    http://opensource.org/licenses/BSD-3-Clause
*/

namespace mcl { namespace fp {

/*
    convert x[0..n) to hex string
    start "0x" if withPrefix
*/
template<class T>
void toStr16(std::string& str, const T *x, size_t n, bool withPrefix = false)
{
    size_t fullN = 0;
    if (n > 1) {
        size_t pos = n - 1;
        while (pos > 0) {
            if (x[pos]) break;
            pos--;
        }
        if (pos > 0) fullN = pos;
    }
    const T v = n == 0 ? 0 : x[fullN];
    const size_t topLen = cybozu::getHexLength(v);
    const size_t startPos = withPrefix ? 2 : 0;
    const size_t lenT = sizeof(T) * 2;
    str.resize(startPos + fullN * lenT + topLen);
    if (withPrefix) {
        str[0] = '0';
        str[1] = 'x';
    }
    cybozu::itohex(&str[startPos], topLen, v, false);
    for (size_t i = 0; i < fullN; i++) {
        cybozu::itohex(&str[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i], false);
    }
}

/*
    convert x[0..n) to bin string
    start "0b" if withPrefix
*/
template<class T>
void toStr2(std::string& str, const T *x, size_t n, bool withPrefix)
{
    size_t fullN = 0;
    if (n > 1) {
        size_t pos = n - 1;
        while (pos > 0) {
            if (x[pos]) break;
            pos--;
        }
        if (pos > 0) fullN = pos;
    }
    const T v = n == 0 ? 0 : x[fullN];
    const size_t topLen = cybozu::getBinLength(v);
    const size_t startPos = withPrefix ? 2 : 0;
    const size_t lenT = sizeof(T) * 8;
    str.resize(startPos + fullN * lenT + topLen);
    if (withPrefix) {
        str[0] = '0';
        str[1] = 'b';
    }
    cybozu::itobin(&str[startPos], topLen, v);
    for (size_t i = 0; i < fullN; i++) {
        cybozu::itobin(&str[startPos + topLen + i * lenT], lenT, x[fullN - 1 - i]);
    }
}

/*
    convert hex string to x[0..xn)
    hex string = [0-9a-fA-F]+
*/
template<class T>
void fromStr16(T *x, size_t xn, const char *str, size_t strLen)
{
    if (strLen == 0) throw cybozu::Exception("fp:fromStr16:strLen is zero");
    const size_t unitLen = sizeof(T) * 2;
    const size_t q = strLen / unitLen;
    const size_t r = strLen % unitLen;
    const size_t requireSize = q + (r ? 1 : 0);
    if (xn < requireSize) throw cybozu::Exception("fp:fromStr16:short size") << xn << requireSize;
    for (size_t i = 0; i < q; i++) {
        bool b;
        x[i] = cybozu::hextoi(&b, &str[r + (q - 1 - i) * unitLen], unitLen);
        if (!b) throw cybozu::Exception("fp:fromStr16:bad char") << cybozu::exception::makeString(str, strLen);
    }
    if (r) {
        bool b;
        x[q] = cybozu::hextoi(&b, str, r);
        if (!b) throw cybozu::Exception("fp:fromStr16:bad char") << cybozu::exception::makeString(str, strLen);
    }
    for (size_t i = requireSize; i < xn; i++) x[i] = 0;
}


} } // mcl::fp