#include <iostream>
#include <math.h>

using namespace std;

/*!
\brief Permute deux reels.
\param a,b Reels echanges.
*/
void Echange(float &a, float &b)
{
    float x = a;
    a = b;
    b = x;
}

/*!
\brief Teste si un entier est premier.
\param a Entier.
*/
bool Premier(int a)
{
    // En fait on pourrait n'aller que jusqu'a la racine de a, mais
    // pour cela il faudrait avoir la racine. A la place, on va
    // jusque a
    for (int i = 2; i < a; i++)
    {
        if (a % i == 0)
            return false;
    }
    return true;
}

/*!
\brief Teste si un entier est parfait.
\param a Entier.
*/
bool Parfait(int a)
{
    int s = 1;
    for (int i = 2; i < a; i++)
    {
        if (a % i == 0)
        {
            s += i;
        }
    }
    if (s == a)
    {
        return true;
    }
    else
    {
        return false;
    }
}

/*!
\brief Suite de Syracuse.
\param u0 Entier de depart.
\param n Nombre d'iterations.
*/
int Syracuse(int u0, int n)
{
    int u = u0;
    for (int i = 0; i < n; i++)
    {
        if (u % 2 == 0)
        {
            u /= 2;
        }
        else
        {
            u = 3 * u + 1;
        }
    }
    return u;
}

/*!
\brief Racine carree par suite convergente.
\param a Reel.
\param n Nombre d'iterations.
*/
float Racine(float a, int n)
{
    float x = a;
    for (int i = 0; i < n; i++)
    {
        x = (x + a / x) / 2.0;
    }
    return x;
}

/*!
\brief Racine carree par suite convergente.
\param a Reel.
\param e Précision.
*/
float RacineE(float a, float e)
{
    float x = a;
    while (fabs(x * x - a) > e)
    {
        x = (x + a / x) / 2.0;
    }
    return x;
}

/*!
\brief Racine carree par dichotomie.
\param a Reel.
\param e Précision.
*/
float RacineD(float a, float e)
{
    // A depart, la racine est forcement dans l'intervalle [0,a] si a>1
    // et [0,1] si a<1 donc, dans [0,max(1,a)]

    // Bornes de depart
    float x = 0.0;
    float y = max(1.0f, a);

    // Tant que l'intervalle n'est pas assez petit
    while (y - x > e)
    {
        // Milieu
        float m = (x + y) / 2.0;
        if (m * m < a)
        {
            x = m;
        }
        else
        {
            y = m;
        }
    }
    return x;
}
/*!
\brief Calcul un nombre aleatoire entre deux valeurs
\param a,b Bornes.
*/
float Alea(float a, float b)
{
    const int N = 648792;
    float t = float(rand() % N) / float(N - 1);
    return (1.0 - t) * a + t * b;
}

int main()
{
    cout << "Primes" << endl;
    for (int i = 1; i < 100; i++)
    {
        if (Premier(i))
        {
            cout << i << ' ';
        }
    }
    cout << endl;
    cout << "Parfaits" << endl;
    for (int i = 1; i < 100; i++)
    {
        if (Parfait(i))
        {
            cout << i << ' ';
        }
    }
    cout << endl;

    cout << "Racine de " << 7 << " = " << Racine(7.0, 12) << endl;
    cout << "Racine de " << 8 << " = " << RacineE(8.0, 0.0001) << endl;
    cout << "Racine de " << 5 << " = " << RacineD(5.0, 0.0001) << endl;
    return 0;
}