aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/int128/int128.cpp
blob: dedcd28f9165dcdfc45e612a79c80c5c2a43d646 (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
#include "int128.h" 
 
#include <tuple> 
 
IOutputStream& operator<<(IOutputStream& out, const ui128& other) { 
    // see http://stackoverflow.com/questions/4361441/c-print-a-biginteger-in-base-10 
    // and http://stackoverflow.com/questions/8023414/how-to-convert-a-128-bit-integer-to-a-decimal-ascii-string-in-c 
    int d[39] = {0}; 
    int i; 
    int j; 
    for (i = 63; i > -1; i--) { 
        if ((other.High_ >> i) & 1) 
            ++d[0]; 
        for (j = 0; j < 39; j++) 
            d[j] *= 2; 
        for (j = 0; j < 38; j++) { 
            d[j + 1] += d[j] / 10; 
            d[j] %= 10; 
        } 
    } 
    for (i = 63; i > -1; i--) { 
        if ((other.Low_ >> i) & 1) 
            ++d[0]; 
        if (i > 0) 
            for (j = 0; j < 39; j++) 
                d[j] *= 2; 
        for (j = 0; j < 38; j++) { 
            d[j + 1] += d[j] / 10; 
            d[j] %= 10; 
        } 
    } 
    for (i = 38; i > 0; i--) 
        if (d[i] > 0) 
            break; 
    for (; i > -1; i--) 
        out << static_cast<char>('0' + d[i]); 
 
    return out; 
} 
 
void TSerializer<ui128>::Save(IOutputStream* out, const ui128& Number) { 
    ::Save(out, GetHigh(Number)); 
    ::Save(out, GetLow(Number)); 
} 
 
void TSerializer<ui128>::Load(IInputStream* in, ui128& Number) { 
    ui64 High; 
    ui64 Low; 
    ::Load(in, High); 
    ::Load(in, Low); 
    Number = ui128(High, Low); 
} 

IOutputStream& operator<<(IOutputStream& out, const i128& other)
{
    if (other >= 0) {
        out << ui128{other};
    } else {
        out << '-' << ui128{-other};
    }
    return out;
}