View difference between Paste ID: PKCcfRLt and p1NAeAiL
SHOW: | | - or go back to the newest paste.
1
#include <cstdlib>
2
#include <string>
3
#include <iostream>
4
#include <boost/cstdint.hpp>
5
#include <boost/integer.hpp>
6
#include <gmp.h>
7
8
using namespace std;
9
using namespace boost;
10
11
typedef struct sol {
12
    mpz_t p;
13
    mpz_t q;
14
} sol_t;
15
16
// Left classifier
17
void lc(mpz_t * l, const mpz_t * x1, const mpz_t * x2) {
18
    mpz_t sub1, div1;
19
    /* Apply l = (((x2-x1)*0.25) + x1 )^2 */
20
21
    /* Substract low bound from high bound */
22
    mpz_sub(sub1, *x2, *x1);
23
    /* Divide by 4 */
24
    mpz_tdiv_q_2exp(div1, sub1, 2);
25
    /* Add low bound */
26
    mpz_add(*l, div1, *x1);
27
    /* Powerize to 2 */
28
    mpz_pow_ui(*l, *l, 2);
29
}
30
31
void rc(mpz_t * r, const mpz_t * x1, const mpz_t * x2) {
32
    mpz_t sub1, tmp1, tmp2, sum1, div1;
33
    /* Apply: ((0.75 * (x2-x1)) + x1)^2 + 
34
              ((2*(0.5  * (x2-x1)) + x1)^2) - lc(x1, x2) - 
35
              ((0.75 * (x2-x1)) + x1)^2 */
36
    /* Substract low bound from high bound */
37
    mpz_sub(sub1, *x2, *x1);
38
    /* Divide by 2 */
39
    mpz_tdiv_q_2exp(div1, sub1, 1);
40
    /* Add low bound */
41
    mpz_add(sum1, div1, *x1);
42
    /* Powerize to 2 */
43
    mpz_pow_ui(tmp1, sum1, 2);
44
    /* Multiply by 2 */
45
    mpz_mul_2exp(tmp1, tmp1, 1);
46
    /* Left classifier */
47
    lc(&tmp2, x1, x2);
48
    /* Add low bound */
49
    mpz_sub(*r, tmp1, tmp2);
50
}
51
52
void factImpl(const mpz_t * k, mpz_t * l, mpz_t * h) {
53
    // Continue until granularity is not unity 
54
    mpz_t sub1, div1, tmp1, tmp2;
55
    while ( mpz_cmp(*h, *l) >= 0 ) {
56
        /* h - l */
57
        mpz_sub(sub1, *h, *l);
58
        /* Divide by 2 */
59
        mpz_tdiv_q_2exp(div1, sub1, 1);
60
        /* euclidian left part */
61
        lc(&tmp1, l, h);
62
        mpz_sub(tmp1, *k, tmp1);
63
        mpz_abs(tmp1, tmp1);
64
        rc(&tmp2, l, h);
65
        mpz_sub(tmp2, *k, tmp2);
66
        mpz_abs(tmp2, tmp2);
67
        if ( mpz_cmp(tmp2, tmp1) > 0 ) {
68
            mpz_sub(*h, *h, div1);
69
            if ( mpz_cmp(*l, *h) > 0 ) {
70
                mpz_add_ui(*h, *l, 1);
71
            }
72
        } else {
73
            mpz_add_ui(*l, *l, 1);
74
        }
75
    }
76
}
77
78
void follow_impl(const mpz_t * k, 
79
                 mpz_t * x, mpz_t * y,
80
                 const int dx, const int dy,
81
                 const mpz_t * w, const mpz_t * h) {
82
    mpz_t c, lh, hh, hl, ll, xi, yi, xy, xiy, xyi, xiyi, iix, iiy;
83
    /* Initial warmup */
84
    lc(&c, x, y);
85
    mpz_set_si(iix, dx);
86
    mpz_set_si(iiy, dy);
87
    mpz_add(xi, *x, iix);
88
    mpz_add(yi, *y, iiy);
89
    mpz_mul(xy, *x, *y);
90
    mpz_mul(xiy, xi, *y);
91
    mpz_mul(xyi, *x, yi);
92
    mpz_mul(xiyi, xi, yi);
93
94
    do {
95
        /* compute ll */
96
        mpz_sub(ll, xy, *k);
97
        mpz_abs(ll, ll);
98
        /* compute hl */
99
        mpz_sub(hl, xyi, c);
100
        mpz_abs(hl, hl);
101
        /* compute lh */
102
        mpz_sub(lh, xiy, c);
103
        mpz_abs(lh, lh);
104
        /* compute hh */
105
        mpz_sub(hh, xiyi, c);
106
        mpz_abs(hh, hh);
107
108
        /* Check if found */
109
        if ( mpz_sgn(ll) == 0 ) {
110
            break;
111
        } else if ( mpz_cmp(hl, hh) > 0 && mpz_cmp(lh, hh) > 0) {
112
            mpz_add(*x, *x, iix);
113
            mpz_add(*y, *y, iiy);
114
        } else if ( mpz_cmp(hl, lh) > 0 ) {
115
            mpz_add(*x, *x, iix);
116
        } else {
117
            mpz_add(*y, *y, iiy);
118
        }
119
        mpz_add(xi, *x, iix);
120
        mpz_add(yi, *y, iiy);
121
        mpz_mul(xy, *x, *y);
122
        mpz_mul(xiy, xi, *y);
123
        mpz_mul(xyi, *x, yi);
124
        mpz_mul(xiyi, xi, yi);
125
    } while( mpz_cmp(*w, xi) > 0 && mpz_cmp_ui(xi, 1) > 0 && 
126
            mpz_cmp(*h, yi) > 0 && mpz_cmp_ui(yi, 1) > 0);
127
}
128
void 
129
resolve(const mpz_t * product, sol *prims) {
130
    mpz_t hl, hh, x, y, pq;   // Hyperbol bounds (low bound and high bound)
131
132
    mpz_set_ui(prims->p, 0);
133
    mpz_set_ui(prims->q, 0);
134
135
    mpz_set(hh, *product);
136
    factImpl(product, &hl, &hh);
137
    mpz_set(x, hl);
138
    mpz_set(y, hh);
139
    std::cerr << "Analysis hyperbol direction: up-right" << std::endl;
140
    follow_impl( product, &x, &y, 1, -1, product, product );
141
    mpz_mul(pq, x, y);
142
    mpz_set(x, hl);
143
    mpz_set(y, hh);
144
    if ( mpz_cmp(pq, *product) != 0) {
145
        std::cerr << "Analysis hyperbol direction: down-left" << std::endl;
146
        follow_impl( product, &x, &y, -1, 1, product, product );
147
        mpz_mul(pq, x, y);
148
    }
149
    if ( mpz_cmp(pq, *product) != 0) {
150
        mpz_set(prims->p, x);
151
        mpz_set(prims->p, y);
152
    }
153
}
154
155
int main(int argc, char *argv[]) {
156
    typedef mpz_t bigint_t;
157
    if(2 == argc) {
158
        bigint_t pq;
159
        sol_t res;
160
        mpz_set_ui(res.p, 0);
161
        mpz_set_ui(res.q, 0);
162
        mpz_init_set_str(pq, argv[1], 10);
163
        resolve(&pq, &res);
164
        printf("solution: pq = (p*q) =\n");
165
        mpz_out_str(stdout, 10, res.p);
166
        printf("\n*\n");
167
        mpz_out_str(stdout, 10, res.q);
168
    } else {
169
        printf("Usage: %s <p*q>\n", argv[0]);
170
        return -1;
171
    }
172
    return 0;
173
}