#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <malloc.h>
#include <string.h>

void summ(unsigned a[16], unsigned b[16], unsigned c[16]) //a = b + c //correct
{
    int i;
    int flag = 0;
    unsigned long long res;

    for(i = 0; i < 16; i++)
    {
        res = b[i];
        res += c[i] + flag;
        a[i] = res;
        flag = res >> 32;
    }
}

void neg(unsigned x[16]) // -x //correct
{
    int i;

    for(i = 0; i < 16; i++)
    {
        x[i] = ~x[i];
    }

    for(i = 0; i < 16; i++)
    {
        x[i]++;

        if(x[i] != 0)
        {
            break;
        }
    }
}

void mult(unsigned a[16], unsigned b[16], unsigned c) // a = b * c //correct
{
    int i;
    int flag = 0;
    unsigned long long res;

    for(i = 0; i < 16; i++)
    {
        res = b[i];
        res = res*c + flag;
        a[i] = res;
        flag = res >> 32;
    }
}

void divide(unsigned a[16], unsigned b[16], unsigned c) // a = b / c //correct
{
    int i;
    int flag = 0;
    unsigned long long d;
    unsigned long long res;

    for(i = 15; i >= 0; i--)
    {
        res = b[i];
        d = flag;
        res += d << 32;
        a[i] = res/c;
        flag = res % c;
    }
}

void longtodecimal(unsigned a[10], unsigned b[100], unsigned x[16]) // a[10]...a[1]a[0].b[1]b[2]...b[100]...
{
    unsigned x1[16];
    unsigned x2[16];
    unsigned x3[16];
    unsigned y[16];
    unsigned y1[16];
    unsigned y2[16];
    int i;
    int j;

    memcpy(y, x, 16*sizeof(unsigned));

    for (i = 0; i < 10; i++) //wrong перевод целой части
    {
        memcpy(x1, x, 16*sizeof(unsigned));

        for(j = 0; j < 12; j++)
        {
            x1[j] = 0;
        }

        divide(x2, x1, 10);
        memcpy(x, x2, 16*sizeof(unsigned));

        for(j = 12; j < 16; j++)
        {
            x2[j] = 0;
        }

        mult(x3, x2, 10);
        a[i] = x3[12];
    }

    for(i = 0; i < 100; i++) //wrong перевод дробной части
    {
        memcpy(y1, y, 16*sizeof(unsigned));

        for(j = 12; j < 16; j++)
        {
            y1[j] = 0;
        }

        mult(y2, y1, 10);
        memcpy(y, y2, 16*sizeof(unsigned));
        b[i] = y2[12];
    }
}

void arctan(unsigned x[16], int arg) // arctan(1/arg) //correct
{
    unsigned x1[16];
    unsigned x2[16];
    unsigned sprom[16];
    unsigned sfinal[16];
    unsigned x3[16];
    int i;
    int k = 1;

    for(i = 0; i < 16; i++)
    {
        x1[i] = 0;
        sprom[i] = 0;
    }

    x1[12] = 1;

    divide(x2, x1, arg);
    summ(sfinal, sprom, x2);
    memcpy(sprom, sfinal, 16*sizeof(unsigned)); // artan = 1/arg
    memcpy(x1, x2, 16*sizeof(unsigned));
    k = 3;

    for(i = 1; i < 7000; i++)
    {
        divide(x2, x1, arg*arg);
        memcpy(x3, x2, 16*sizeof(unsigned));

        divide(x2, x3, k);

        if(i % 2 == 1)
        {
            neg(x2);
        }

        summ(sfinal, sprom, x2);
        memcpy(sprom, sfinal, 16*sizeof(unsigned));
        memcpy(x1, x3, 16*sizeof(unsigned));
        k = k + 2;
    }

    memcpy(x, sfinal, 16*sizeof(unsigned));
}

void find_Pi(unsigned x[16]) //correct
{
    unsigned x1[16];
    unsigned x2[16];
    unsigned x3[16];
    unsigned atn18[16];
    unsigned atn57[16];
    unsigned atn239[16];
    unsigned s1[16];
    unsigned s2[16];
    arctan(atn18, 18);
    arctan(atn57, 57);
    arctan(atn239, 239);
    mult(x1, atn18, 12);
    mult(x2, atn57, 8);
    mult(x3, atn239, 5);
    neg(x3);
    summ(s1, x1, x2);
    summ(s2, s1, x3);
    mult(x, s2, 4);
}

int main(void)
{
    //FILE *outp;
    unsigned a[10];
    unsigned b[100];
    unsigned x[16];
    unsigned c[16];
    unsigned d[16];
    int p = 9;
    int i;

    find_Pi(x);

    /*for(i = 0; i < 16; i++)
    {
        d[i] = 0;
    }

    d[12] = 1;
    mult(c, d, 12);
    summ(d, c, x);
    memcpy(x, d, 16*sizeof(unsigned));*/ //Тут я делал Пи+12 чтоб проверить, выводит ли правильно две цифры целой части полученного числа

    longtodecimal(a, b, x);

    while(a[p] == 0)
    {
        p--;
    }

    for(i = p; i >= 0; i--)
    {
        printf("%u", a[i]);
    }

    printf(".");

    for(i = 0; i < 100; i++)
    {
        printf("%u", b[i]);
    }

    return 0;
}