/// G. Hagopian  -- Babylonian

#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;

bool debug{true};

inline double abs(double x) {
    return (x>0 ? x : -x);
}

/// Prototypes (note that gcd() is overloaded)
unsigned int gcd(unsigned int, unsigned int);
unsigned int gcd(unsigned int, unsigned int, unsigned int);
double sqroot(double);
void findExactSimplifiedSolutions(int, int, int);
void findApproximateSolutions(double, double, double);

int main() {
    char yesOrNo;
    cout << "\nThis program will solve a quadratic equation in either integer \n(exact) mode"
         << "or floating point (approximate) mode.\n"
         << "\nDoes your quadratic have integer coefficients (y/n)? ";
    cin >> yesOrNo;
    if(toupper(yesOrNo)=='Y') {
        int a,b,c;
        cout << "\nOk. Enter three integer coefficients, a, b, and c: ";
        while(cin >> a >> b >> c) {
            findExactSimplifiedSolutions(a,b,c);
            cout << "\nOk. Enter integer coefficients, a, b, and c (q to quit): ";
        }
        cin.clear();
    }
    else if(toupper(yesOrNo)=='N') {
        double a,b,c;
        cout << "\nOk. Enter three floating point coefficients, a, b, and c: ";
        while(cin >> a >> b >> c) {
            findApproximateSolutions(a,b,c);
            cout << "\nOk. Enter floating point coefficients, a, b, and c (q to quit): ";
        }
    } ///end else if
} /// end main()

/// Function definitions

double sqroot(double A) {
    vector<double> xs;
    double toler = A*1.e-12;
    double xtemp = A/2, x;
    xs.push_back(xtemp);
    ///prime the pump
    x = (A/xtemp+xtemp)/2;
    xs.push_back(x);
    while(abs(x-xtemp)>toler) {  ///x-xtemp>toler || xtemp-x>toler) {
        if(debug) {
            cout << setprecision(15)
                 << "\nxtemp = " << xtemp
                 << "\nx = " << x;
        }
        xtemp = x;
        x = (A/xtemp+xtemp)/2;
        if(debug) {
            xs.push_back(x);
            cin.get();  ///pause
        }
    }
    if(debug) {
        ///report on iterations
        for(int i = 0; i < xs.size()-1; ++i) {
            cout << "\nThe difference: x[" << i+1 << "] - x["
                 << i << "] = " << xs[i+1]-xs[i];
            cout << "\nThe ratio: x[" << i+1 << "] / x["
                 << i << "] = " << xs[i+1]/xs[i];
        }
    }
    return x;

}

void findExactSimplifiedSolutions(int a, int b, int c) {
    cout << "\nThe gcd(" << a << ", " << b << ", " << c << ") = "
         << gcd(a,b,c);
    /// Write your code here
}

void findApproximateSolutions(double a, double b, double c) {
    if(b>0)
    {
        cout << "\nThe solutions to " << a << "*x^2 + "
             << b << "x";
    }
    else if(b<0)
    {
        cout << "\nThe solutions to " << a << "*x^2 - "
             << -b << "*x";
    }
    else cout << "\nThe solutions to " << a << "*x^2";
    if(c>0) cout << " + " << c;
    else if(c<0) cout << " - " << -c;
    cout << " = 0 are\n";
    /// Write your code here
}

unsigned int gcd(unsigned int a, unsigned int b) {
    if(b == 0) { ///base case
	        return a;
	}
	else  {
		return gcd(b, a % b);
	}
}

unsigned int gcd(unsigned int a, unsigned int b, unsigned int c) {
    if(c == 0 || b==0)
        return gcd(a,b);
    else {
        if(debug) {
            cout << "\ngcd(" << c << ',' << a%c << ',' << b%c << endl;
        }
        return gcd(c, a % c, b % c);
    }

}

/**
http://mathforum.org/library/drmath/view/66043.html
original {x,y,z} = {203,91,77}
   203 = 2*77 + 49,
    91 = 1*77 + 14,

   new {x,y,z} = {77,49,14},
   77 = 5*14 + 7,
   49 = 3*14 + 7,

   new {x,y,z} = {14,7,7},
   14 = 2*7 + 0,
    7 = 1*7 + 0,
*/
