-module(print_hej).
-export([main/1, pow/2]).

main(Args) ->
    Decimals = case Args of
                   [] -> 100;
                   [X | _] ->
                       case string:to_integer(X) of
                           {D, _} when D > 0 -> D;
                           _ -> 100
                       end
               end,
    
    Pi = calculate_pi(Decimals),
    PiStr = format_pi(Pi, Decimals),
    io:format("~s~n", [PiStr]),
    erlang:halt(0).

% Calculate arctan(1/x) using Taylor series
% arctan(1/x) = 1/x - 1/(3*x^3) + 1/(5*x^5) - ...
arctan(X, Decimals) ->
    Scale = pow(10, Decimals + 10),
    XSquared = X * X,
    Term = Scale div X,  % First term: scale / x
    arctan_iter(XSquared, Term, 0, 0, Decimals).

arctan_iter(_XSquared, Term, N, Result, Decimals) when Term == 0; N > Decimals * 3 ->
    Result;
arctan_iter(XSquared, Term, N, Result, Decimals) ->
    Divisor = 2 * N + 1,
    Contrib = Term div Divisor,
    NewResult = case N rem 2 of
                   0 -> Result + Contrib;
                   1 -> Result - Contrib
               end,
    NewTerm = Term div XSquared,  % Divide by x² each iteration
    arctan_iter(XSquared, NewTerm, N + 1, NewResult, Decimals).

% Calculate pi using Machin's formula
% pi/4 = 4*arctan(1/5) - arctan(1/239)
calculate_pi(Decimals) ->
    Atan1_5 = arctan(5, Decimals),
    Atan1_239 = arctan(239, Decimals),
    16 * Atan1_5 - 4 * Atan1_239.

% Format pi with decimal point
format_pi(Pi, Decimals) ->
    PiStr = integer_to_list(Pi),
    % Pad with leading zeros if needed
    PiStr2 = case length(PiStr) < Decimals + 10 of
                true -> string:left(PiStr, Decimals + 10, $0);
                false -> PiStr
            end,
    "3." ++ string:substr(PiStr2, 2, Decimals).

% Power function for integers
pow(Base, Exp) when Exp >= 0 ->
    pow_iter(Base, Exp, 1).

pow_iter(_Base, 0, Acc) -> Acc;
pow_iter(Base, Exp, Acc) when Exp rem 2 == 0 ->
    pow_iter(Base * Base, Exp div 2, Acc);
pow_iter(Base, Exp, Acc) ->
    pow_iter(Base, Exp - 1, Acc * Base).