# AxiomX-0.0.1
# A dynamic math library

from time import sleep

"""
This library is a project initiated by Eric Joseph. It contains a large amount of methods.
Here are the methods of AxiomX:
  1.  absolute(x)                               - Returns the absolute value of x.
  2.  get_digits(x)                             - Returns the digits of x in a list.
  3.  gamma(x)                                  - It returns the value of gamma(x). It only is accurate for 0.5 and other integers. It is still under research.
  4.  factorial(x)                              - It is based on the gamma function.
  5.  continued_fraction(constant)              - This method returns the list of the denominators of the simple continued fraction of the constant. An additional argument can be supplied for the no. of denominators.
  6.  evaluate_continued_fraction(denominators) - This method evaluates a continued fraction by the list of denominators supplied.
  7.  sqrt(n)                                   - This method returns the square root of n using Newton-Raphson Method.
  8.  zeta(n)                                   - This method returns the value of the Riemann zeta function at n. Throws an error if n <= 1.
  9.  exp(n)                                    - This method returns the value of e**n.
  10. ln(x)                                     - This method returns the natural logarithm of x.
  11. log10(x)                                  - This method returns the common logarithm of x.
  12. log(a, b)                                 - This method returns the logarithm of a to the base b.
  13. radians(degrees)                          - This method converts degrees into radians.
  14. degrees(radians)                          - This method converts radians to degrees.
  15. sin(x)                                    - This method gives the value of sin(x), where x is in radians.
"""

print("AxiomX loading...")
sleep(3)
print("AxiomX is ready to use!\n")
version = "0.0.1"

# Constants
pi = 3.141592653589793
e = 2.718281828459045
tau = 2 * pi
lemniscate = 2.622057554292119

# Number Operations

def absolute(x):
    if x >= 0:
        return x
    return -x

def get_digits(x):
    digits = []
    while x > 0:
        digits.append(x % 10)
        x //= 10
    digits.reverse()
    return digits

def gamma(x):
    # Lanczos approximation constants
    p = [
        0.99999999999980993,
        676.5203681218851,
        -1259.1392167224028,
        771.32342877765313,
        -176.61502916214059,
        12.507343278686905,
        -0.13857109526572012,
        9.9843695780195716e-6,
        1.5056327351493116e-7
    ]

    if x < 0.5:
        # Reflection formula
        return pi / (sin(pi * x) * gamma(1 - x))

    x -= 1
    t = p[0]
    for i in range(1, len(p)):
        t += p[i] / (x + i)

    g = 7
    return sqrt(2 * pi) * (x + g + 0.5)**(x + 0.5) * (e**(-(x + g + 0.5))) * t

def factorial(x):
    return gamma(x+1)
    
def continued_fraction(constant, terms=5):
    denominator = []
    denominator.append(int(constant))
    for i in range(terms-1):
        constant = constant - denominator[i]
        denominator.append(int(float(1) / float(constant)))
        constant = 1 / constant
    return denominator
    
def evaluate_continued_fraction(denominators):
    result = 0
    for denominator in reversed(denominators):
        result = denominator + (1 / result) if result != 0 else denominator
    return result

def sqrt(n):
    if n < 0:
        raise ValueError("square root of negative number is imaginary")
    x1 = int(n**0.5)
    x2 = 0
    if n == 0:
        return 0
    for a in range(100000):
        x2 = 0.5 * (x1 + (n / x1))
        x1 = x2
    return x1
    
# Riemann Zeta function
def zeta(n):
    if n <= 1:
        raise ValueError("zeta(n) is undefined for n <= 1")
    zetval = 0
    for b in range(100000):
        zetval += 1 / ((b+1)**n)
    return zetval
    
# Defining more constants
gelfond = e**pi
sqrt_2 = sqrt(2)
sqrt_3 = sqrt(3)
sqrt_5 = sqrt(5)
golden_ratio = (1 + sqrt_5) / 2
silver_ratio = 1 + sqrt_2
apery = zeta(3)
gauss = lemniscate / pi
ramanujan = gelfond**sqrt(163)
euler_mascheroni = 0.577215664901533

# Exponential functions
def exp(n):
    return e**n
    
def ln(x, terms=100):
    if x <= 0:
        raise ValueError("ln(x) is undefined for x <= 0")
    y = (x - 1) / (x + 1)
    result = 0.0
    for n in range(terms):
        term = (y ** (2 * n + 1)) / (2 * n + 1)
        result += term
    return 2 * result

def log10(x, terms=100):
    return ln(x, terms) / ln(10, terms)
    
def log(argument, base):
    return log10(argument) / log10(base)
    
#Trig Functions

def radians(deg):
    return (pi/180)*deg
    
def degrees(rad):
    return (180/pi)*rad
    
def sin(x, terms=20):
    quarter = ((x // tau) + 1) % 4
    if x == pi:
        return 0
    x = x % tau
    # Input validation
    if not isinstance(x, (int, float)):
        raise TypeError("x must be a number (int or float).")
    if not isinstance(terms, int) or terms <= 0:
        raise ValueError("terms must be a positive integer.")
    sine_value = 0.0
    for n in range(terms):
        term = ((-1)**n) * (x**(2*n + 1)) / factorial(2*n + 1)
        sine_value += term
    return sine_value
    if quarter == 1:
        return sine_value
    elif quarter == 2:
        return sqrt(1 - (sine_value**2))
    elif quarter == 3:
        return -sine_value
    elif quarter == 0:
        return -sqrt(1 - (sine_value**2))
        
def cos(x):
    return sin((pi/2)-x)
    
def tan(x):
    return sin(x) / cos(x)

def cot(x):
    return 1 / tan(x)

def sec(x):
    return 1 / cos(x)
    
def cosec(x):
    return 1 / sin(x)

def arcsin(x, iterations=10):
    if abs(x) > 1:
        raise ValueError("x must be in [-1, 1]")
    y = x
    for _ in range(iterations):
        y -= (sin(y) - x) / cos(y)
    return y
    
def arccos(x):
    return (pi / 2) - arcsin(x)
    
def arctan(x):
    return arcsin(x / sqrt(1+ x**2))
    
def arccot(x):
    return (pi/2) - arctan(x)

def arcsec(x):
    return arccos(1/x)
    
def arccosec(x):
    return arcsin(1/x)
    
def sinh(x):
    return (e**x - e**(-x))/2
    
def cosh(x):
    return (e**x + e**(-x))/2
    
def tanh(x):
    return sinh(x) / cosh(x)
    
def coth(x):
    return cosh(x) / sinh(x)
    
def sech(x):
    return 1 / cosh(x)
    
def cosech(x):
    return 1 / sinh(x)
    
def arcsinh(x):
    return ln(x + sqrt(x**2 + 1))
    
def arccosh(x):
    return abs(arcsinh(sqrt(x**2 - 1)))
    
def arccoth(x):
    return 0.5 * ((x+1)/(x-1))
    
def arctanh(x):
    return arccoth(1/x)
    
def arcsech(x):
    return arccosh(1/x)
    
def arccosech(x):
    return arcsinh(1/x)