// Arup Guha
// 10/23/2024
// Example illustrating Fermat Factoring.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#define DEBUG 1

long long isPerfectSquare(long long n);
void fermatfactor(long long n);

int main() {

    // Two test cases...
    fermatfactor(1081);
    fermatfactor(38482027);
    return 0;
}

// Will only work for smaller integers, didn't code for long long.
void fermatfactor(long long n) {

    // First value of x is the smallest integer > sqrt(n).
    long long start = sqrt(n);
    while (start*start <= n) start++;

    // We just keep going until we find a factorization.
    while (1) {

        // The value we'll test to see if it's a perfect square.
        long long testVal = start*start - n;

        // So you can see the algorithm running, if you want.
        if (DEBUG) {
            printf("Trying %lld, leftover = %lld\n", start, testVal);
        }

        // Try it out.
        long long retval = isPerfectSquare(testVal);

        // We found a perfect square, so let's print out the factorization and stop!
        if (retval != -1) {
            long long small = start - retval;
            long long big = start + retval;
            printf("%lld = %lld x %lld\n", n, small, big);
            break;
        }

        // Go to the next...
        start++;
    }
}

// If n is a perfect square its square root is returned. Otherwise, -1 is returned.
long long isPerfectSquare(long long n) {

    long long low = 0, high = n;

    // Running binary search for square root of n.
    while (low <= high) {

        long long mid = (low+high)/2;

        // Guess was too big.
        if (mid*mid > n)
            high = mid-1;

        // Guess was too small.
        else if (mid*mid < n)
            low = mid+1;

        // n is mid squared, so n is a perfect square.
        else
            return mid;
    }

    // n is not a perfect square.
    return -1;
}
