Fixed small errors in ddFunction.py
authorAntonio Jimenez Pastor <antonio@ebook.dk-compmath.jku.at>
Tue, 11 Sep 2018 15:24:39 +0000 (17:24 +0200)
committerAntonio Jimenez Pastor <antonio@ebook.dk-compmath.jku.at>
Tue, 11 Sep 2018 15:24:39 +0000 (17:24 +0200)
Added all the examples from DLMF website.

Started adding the documentation for all the examples.

ajpastor/dd_functions/ddExamples.py
ajpastor/dd_functions/ddFunction.py
releases/diff_defined_functions__0.5.zip
releases/old/diff_defined_functions__0.5__18.09.11_17:24:39.zip [new file with mode: 0644]

index 9ab2a44..f66c7a1 100644 (file)
@@ -1,23 +1,22 @@
 
-# This file was *autogenerated* from the file ./ddExamples.sage
 from sage.all_cmdline import *   # import sage library
 
-
 from sage.rings.polynomial.polynomial_ring import is_PolynomialRing;
 from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing;
 
-_sage_const_3 = Integer(3); _sage_const_2 = Integer(2); _sage_const_1 = Integer(1); _sage_const_0 = Integer(0); _sage_const_6 = Integer(6)
 from ajpastor.dd_functions.ddFunction import *;
 
 from ajpastor.misc.dinamic_string import *;
 
-## Global variables (PUBLIC)
-DFinite_examples = {};
-DDFinite_examples = {};
-
-## Global variables (PRIVATE)
-__example_names = {};
+_sage_const_3 = Integer(3); _sage_const_2 = Integer(2); _sage_const_1 = Integer(1); _sage_const_0 = Integer(0); _sage_const_6 = Integer(6);
 
+### Global variables (PUBLIC)
+#DFinite_examples = {};
+#DDFinite_examples = {};
+#
+### Global variables (PRIVATE)
+#__example_names = {};
+#
 ##################################################################################
 ##################################################################################
 ###
@@ -25,82 +24,150 @@ __example_names = {};
 ###
 ##################################################################################
 ##################################################################################
-def DD_EXAMPLES_LOAD():
-    global DFinite_examples; global DDFinite_examples;
-    global __example_names;
-
-    s = DFinite.element([_sage_const_1 ,_sage_const_0 ,_sage_const_1 ],[_sage_const_0 ,_sage_const_1 ], name=DinamicString("sin(_1)", "x"));
-    c = DFinite.element([_sage_const_1 ,_sage_const_0 ,_sage_const_1 ],[_sage_const_1 ,_sage_const_0 ], name=DinamicString("cos(_1)", "x"));
-    sh = DFinite.element([-_sage_const_1 ,_sage_const_0 ,_sage_const_1 ],[_sage_const_0 ,_sage_const_1 ], name=DinamicString("sinh(_1)", "x"));
-    ch = DFinite.element([-_sage_const_1 ,_sage_const_0 ,_sage_const_1 ],[_sage_const_1 ,_sage_const_0 ], name=DinamicString("cosh(_1)", "x"));
-    ln = DFinite.element([_sage_const_1 ,_sage_const_0 ,(x+_sage_const_1 )],[_sage_const_0 ,_sage_const_1 ], name=DinamicString("log(_1-1)", "x"));
-    e = DFinite.element([-_sage_const_1 ,_sage_const_1 ],[_sage_const_1 ], name=DinamicString("exp(_1)", "x"));
-    tan = DDFinite.element([-_sage_const_2 ,_sage_const_0 ,c**_sage_const_2 ],[_sage_const_0 ,_sage_const_1 ], name=DinamicString("tan(_1)", "x"));
-    
-    ## Defining D-Finite Examples
-    DFinite_examples['e'] = e;
-    DFinite_examples['ln'] = ln;
-    DFinite_examples['sin'] = s;
-    DFinite_examples['cos'] = c;
-    DFinite_examples['sinh'] = sh;
-    DFinite_examples['cosh'] = ch;
-    P = DFiniteP.parameters()[_sage_const_0 ];
-    DFinite_examples['bessel'] = DFiniteP.element([x**2-P**2,x,x**2], name=DinamicString("bessel_J(_1,_2)", ["P","x"]));
-    DFinite_examples['struve'] = DFiniteP.element([(1-P)*x**2+P**2*(P+1),x*(x**2-P**2-P),(2-P)*x**2,x**3], name=DinamicString("pi*struve_H(_1,_2)", ["P","x"]));
-    DFinite_examples['legendre'] = DFiniteP.element([P*(P+_sage_const_1 ), -_sage_const_2 *x,_sage_const_1 -x**_sage_const_2 ], name=DinamicString("legendre_P(_1,_2)", ["P","x"]));
-    DFinite_examples['chebyshev1'] = DFiniteP.element([P**_sage_const_2 ,-x,(_sage_const_1 -x**_sage_const_2 )], name=DinamicString("chebyshev_T(_1,_2)", ["P","x"]));
-    DFinite_examples['chebyshev2'] = DFiniteP.element([P*(P+_sage_const_2 ),-_sage_const_3 *x,_sage_const_1 -x**_sage_const_2 ], name=DinamicString("chebyshev_U(_1,_2)", ["P","x"]));
-    
-    ## Defining DD-Finite Examples
-    DDFinite_examples['esin'] = DDFinite.element([_sage_const_1 ,-c], [_sage_const_1 ], name=DinamicString("exp(sin(_1))", "x"));
-    DDFinite_examples['sine'] = DDFinite.element([e**_sage_const_2 ,-_sage_const_1 ,_sage_const_1 ],[_sage_const_0 ,_sage_const_1 ], name=DinamicString("sin(exp(_1))", "x"));
-    DDFinite_examples['tan'] = [tan, DDFinite.element([_sage_const_0 ,-_sage_const_2 *s*c,c**_sage_const_2 ], [_sage_const_0 ,_sage_const_1 ], name=DinamicString("tan(_1)", "x"))];
-    DDFinite_examples['bernoulli'] = DDFinite.element([x*e-e+_sage_const_1 ,x*(e-_sage_const_1 )],[_sage_const_1 ,-_sage_const_1 /_sage_const_2 ,_sage_const_1 /_sage_const_6 ,_sage_const_0 ]);
-    
-    ## Defining some names
-    __example_names['exp'] = 'e';
-    __example_names['log'] = 'ln';
-    __example_names['sen'] = 'sin';
-    __example_names['tg'] = 'tan';
-
-def DFinite_example(input, n=_sage_const_0 ):
-    if(DFinite_examples.has_key(input)):
-        res = DFinite_examples[input];
-    elif (__example_names.has_key(input) and DFinite_examples.has_key(__example_names[input])):
-        res = DFinite_examples[__example_names[input]];
-    else:
-        raise ValueError('The DD-Function by name %s does not exist' %(input));
-        
-    if(type(res)==list):
-        return res[n];
-    else:
-        return res;
-    
+#def DD_EXAMPLES_LOAD():
+#    global DFinite_examples; global DDFinite_examples;
+#    global __example_names;
+#
+#    s = DFinite.element([_sage_const_1 ,_sage_const_0 ,_sage_const_1 ],[_sage_const_0 ,_sage_const_1 ], name=DinamicString("sin(_1)", "x"));
+#    c = DFinite.element([_sage_const_1 ,_sage_const_0 ,_sage_const_1 ],[_sage_const_1 ,_sage_const_0 ], name=DinamicString("cos(_1)", "x"));
+#    sh = DFinite.element([-_sage_const_1 ,_sage_const_0 ,_sage_const_1 ],[_sage_const_0 ,_sage_const_1 ], name=DinamicString("sinh(_1)", "x"));
+#    ch = DFinite.element([-_sage_const_1 ,_sage_const_0 ,_sage_const_1 ],[_sage_const_1 ,_sage_const_0 ], name=DinamicString("cosh(_1)", "x"));
+#    ln = DFinite.element([_sage_const_1 ,_sage_const_0 ,(x+_sage_const_1 )],[_sage_const_0 ,_sage_const_1 ], name=DinamicString("log(_1-1)", "x"));
+#    e = DFinite.element([-_sage_const_1 ,_sage_const_1 ],[_sage_const_1 ], name=DinamicString("exp(_1)", "x"));
+#    tan = DDFinite.element([-_sage_const_2 ,_sage_const_0 ,c**_sage_const_2 ],[_sage_const_0 ,_sage_const_1 ], name=DinamicString("tan(_1)", "x"));
+#    
+#    ## Defining D-Finite Examples
+#    DFinite_examples['e'] = e;
+#    DFinite_examples['ln'] = ln;
+#    DFinite_examples['sin'] = s;
+#    DFinite_examples['cos'] = c;
+#    DFinite_examples['sinh'] = sh;
+#    DFinite_examples['cosh'] = ch;
+#    P = DFiniteP.parameters()[_sage_const_0 ];
+#    DFinite_examples['bessel'] = DFiniteP.element([x**2-P**2,x,x**2], name=DinamicString("bessel_J(_1,_2)", ["P","x"]));
+#    DFinite_examples['struve'] = DFiniteP.element([(1-P)*x**2+P**2*(P+1),x*(x**2-P**2-P),(2-P)*x**2,x**3], name=DinamicString("pi*struve_H(_1,_2)", ["P","x"]));
+#    DFinite_examples['legendre'] = DFiniteP.element([P*(P+_sage_const_1 ), -_sage_const_2 *x,_sage_const_1 -x**_sage_const_2 ], name=DinamicString("legendre_P(_1,_2)", ["P","x"]));
+#    DFinite_examples['chebyshev1'] = DFiniteP.element([P**_sage_const_2 ,-x,(_sage_const_1 -x**_sage_const_2 )], name=DinamicString("chebyshev_T(_1,_2)", ["P","x"]));
+#    DFinite_examples['chebyshev2'] = DFiniteP.element([P*(P+_sage_const_2 ),-_sage_const_3 *x,_sage_const_1 -x**_sage_const_2 ], name=DinamicString("chebyshev_U(_1,_2)", ["P","x"]));
+#    
+#    ## Defining DD-Finite Examples
+#    DDFinite_examples['esin'] = DDFinite.element([_sage_const_1 ,-c], [_sage_const_1 ], name=DinamicString("exp(sin(_1))", "x"));
+#    DDFinite_examples['sine'] = DDFinite.element([e**_sage_const_2 ,-_sage_const_1 ,_sage_const_1 ],[_sage_const_0 ,_sage_const_1 ], name=DinamicString("sin(exp(_1))", "x"));
+#    DDFinite_examples['tan'] = [tan, DDFinite.element([_sage_const_0 ,-_sage_const_2 *s*c,c**_sage_const_2 ], [_sage_const_0 ,_sage_const_1 ], name=DinamicString("tan(_1)", "x"))];
+#    DDFinite_examples['bernoulli'] = DDFinite.element([x*e-e+_sage_const_1 ,x*(e-_sage_const_1 )],[_sage_const_1 ,-_sage_const_1 /_sage_const_2 ,_sage_const_1 /_sage_const_6 ,_sage_const_0 ]);
+#    
+#    ## Defining some names
+#    __example_names['exp'] = 'e';
+#    __example_names['log'] = 'ln';
+#    __example_names['sen'] = 'sin';
+#    __example_names['tg'] = 'tan';
+#
+#def DFinite_example(input, n=_sage_const_0 ):
+#    if(DFinite_examples.has_key(input)):
+#        res = DFinite_examples[input];
+#    elif (__example_names.has_key(input) and DFinite_examples.has_key(__example_names[input])):
+#        res = DFinite_examples[__example_names[input]];
+#    else:
+#        raise ValueError('The DD-Function by name %s does not exist' %(input));
+#        
+#    if(type(res)==list):
+#        return res[n];
+#    else:
+#        return res;
+#    
+#
+#def DDFinite_example(input, n = _sage_const_0 ):
+#    if(DDFinite_examples.has_key(input)):
+#        res = DDFinite_examples[input];
+#    elif (__example_names.has_key(input) and DDFinite_examples.has_key(__example_names[input])):
+#        res = DDFinite_examples[__example_names[input]];
+#    else:
+#        raise ValueError('The DD-Function by name %s does not exist' %(input));
+#        
+#    if(type(res)==list):
+#        return res[n];
+#    else:
+#        return res;
+#    
+#def DDFunction_example(input, n=_sage_const_0 ):
+#    try:
+#        return DFinite_example(input, n);
+#    except Exception:
+#        pass;
+#    try:
+#        return DDFinite_example(input, n);
+#    except Exception:
+#        pass;
+#        
+#    raise ValueError('No DD-Function by name %s exist' %(input));
 
-def DDFinite_example(input, n = _sage_const_0 ):
-    if(DDFinite_examples.has_key(input)):
-        res = DDFinite_examples[input];
-    elif (__example_names.has_key(input) and DDFinite_examples.has_key(__example_names[input])):
-        res = DDFinite_examples[__example_names[input]];
-    else:
-        raise ValueError('The DD-Function by name %s does not exist' %(input));
+def ddExamples(functions = False, names=False):
+    '''
+        Welcome to ddExamples documentation. Here we describe the functions
+        available in this module. For further information on each function, 
+        please access the documentation for that particular function.
+        
+        All the elements that are returned in this module are DDFunction, i.e.,
+        formal power series defined with a linear differential equation and
+        some appropriate initial values.
         
-    if(type(res)==list):
-        return res[n];
+        When possible, the functions returned by this module are associated with
+        the usual implementation of those functions in SAGE, so using the 
+        method "to_symbolic()" returns the same object in the Symbolic Ring.
+        
+        The functions available in this module are the following:
+        
+        ** TRIGONOMETRIC FUNCTIONS
+            - Sin
+            - Cos
+            - Tan
+            - Sinh
+            - Cosh
+        ** EXPONENTIAL FUNCTIONS
+            - Exp
+            - Log
+            - Log1
+        ** BESSEL TYPE FUNCTIONS (see chapters 10, 11 in https://dlmf.nist.gov)
+            - BesselD
+            - StruveD
+        ** ORTHOGONAL POLRNOMAILS
+            - LegendreD (see chapter 14 in https://dlmf.nist.gov)
+            - ChebyshevD (see chapter 18 in https://dlmf.nist.gov)
+        ** HYPERGEOMETRIC FUNCTIONS (see chapters 15, 16 in https://dlmf.nist.gov)
+            - HypergeometricFunction
+            - GenericHypergeometricFunction
+        ** MATHIEU TYPE FUNCTIONS (see chapter 28 in https://dlmf.nist.gov)
+            - MathieuD
+            - MathieuSin
+            - MathieuCos
+            - ModifiedMathieuD
+            - ModifiedMathieuSin
+            - ModifiedMathieuCos
+            - HillD
+        ** AIRY'S FUNCTIONS
+            - AiryD
+        ** PARABOLIC-CYLINDER TYPE FUNCTIONS
+            - ParabolicCylinderD
+        ** ELLIPTIC INTEGRALS (see chapter 19 in https://dlmf.nist.gov)
+            - EllipticLegendreD
+        ** SPHEROIDAL WAVE FUNCTIONS (see chapter 30 in https://dlmf.nist.gov)
+            - CoulombSpheroidalFunctionD
+            - SpheroidalWaveFunctionD
+        ** HEUN'S FUNCTIONS (see chapter 31 in https://dlmf.nist.gov)
+            - FuschianD
+            - HeunD
+        ** COULOMB WAVE FUNCTION (see chapter 33 in https://dlmf.nist.gov)
+            - CoulombF
+    '''
+    if(not functions):
+        print ddExamples.__doc__;
     else:
-        return res;
-    
-def DDFunction_example(input, n=_sage_const_0 ):
-    try:
-        return DFinite_example(input, n);
-    except Exception:
-        pass;
-    try:
-        return DDFinite_example(input, n);
-    except Exception:
-        pass;
+        funcs =  [Sin,Cos,Tan,Sinh,Cosh,Exp,Log,Log1,BesselD,StruvD,LegendreD,ChebyshevD,HypergeometricFunction,GenericHypergeometricFunction,MathieuD,MathieuSin,MathieuCos,ModifiedMathieuD,ModifiedMathieuSin,ModifiedMathieuCos,HillD,AiryD,ParabolicCylinderD,EllipticLegendreD,CoulombSpheroidalFunctionD,SpheroidalWaveFunctionD,FuschianD,HeunD,CoulombF];
         
-    raise ValueError('No DD-Function by name %s exist' %(input));
+        if(names):
+            return [el.__name__ for el in funcs];
+        return funcs;
+    
 
 ##################################################################################
 ##################################################################################
@@ -111,8 +178,22 @@ def DDFunction_example(input, n=_sage_const_0 ):
 ##################################################################################
 @cached_function
 def Sin(input, ddR = None):
-    from ajpastor.dd_functions.ddFunction import DDFunction;
-    if(isinstance(input, DDFunction)):
+    '''
+        D-finite implementation of the Sine function (sin(x)).
+        
+        References:
+            - http://mathworld.wolfram.com/Sine.html
+            - https://en.wikipedia.org/wiki/Sine
+            
+        This functions allows the user to fix the argument. The argument can be:
+            - A symbolic expression: all variables but "x" will be considered as parameters. Must be a polynomial expression with x as a factor.
+            - A polynomial: the first generator of the polynomial ring will be considered the variable to compute derivatives and the rest will be considered as parameters. The polynomial must be divisible by the main variable.
+            - A DDFunction: the composition will be computed. The DDFunction must have initial value 0.
+            
+        This function can be converted into symbolic expressions.
+    '''
+    
+    if(is_DDFunction(input)):
         return Sin(x)(input);
     f,dR = __decide_parent(input, ddR);
     
@@ -131,8 +212,21 @@ def Sin(input, ddR = None):
 
 @cached_function    
 def Cos(input, ddR = None):
-    from ajpastor.dd_functions.ddFunction import DDFunction;
-    if(isinstance(input, DDFunction)):
+    '''
+        D-finite implementation of the Cosine function (cos(x)).
+        
+        References:
+            - http://mathworld.wolfram.com/Cosine.html
+            - https://en.wikipedia.org/wiki/Cosine
+            
+        This functions allows the user to fix the argument. The argument can be:
+            - A symbolic expression: all variables but "x" will be considered as parameters. Must be a polynomial expression with x as a factor.
+            - A polynomial: the first generator of the polynomial ring will be considered the variable to compute derivatives and the rest will be considered as parameters. The polynomial must be divisible by the main variable.
+            - A DDFunction: the composition will be computed. The DDFunction must have initial value 0.
+            
+        This function can be converted into symbolic expressions.
+    '''
+    if(is_DDFunction(input)):
         return Cos(x)(input);
     f,dR = __decide_parent(input, ddR);
     
@@ -151,8 +245,21 @@ def Cos(input, ddR = None):
 
 @cached_function
 def Tan(input, ddR = None):
-    from ajpastor.dd_functions.ddFunction import DDFunction;
-    if(isinstance(input, DDFunction)):
+    '''
+        DD-finite implementation of the Tangent function (tan(x)).
+        
+        References:
+            - http://mathworld.wolfram.com/Tangent.html
+            - https://en.wikipedia.org/wiki/Tangent
+            
+        This functions allows the user to fix the argument. The argument can be:
+            - A symbolic expression: all variables but "x" will be considered as parameters. Must be a polynomial expression with x as a factor.
+            - A polynomial: the first generator of the polynomial ring will be considered the variable to compute derivatives and the rest will be considered as parameters. The polynomial must be divisible by the main variable.
+            - A DDFunction: the composition will be computed. The DDFunction must have initial value 0.
+            
+        This function can be converted into symbolic expressions.
+    '''
+    if(is_DDFunction(input)):
         return Tan(x)(input);
     if(input == x):
         return DDFinite_example('tan');
@@ -188,8 +295,21 @@ def Tan(input, ddR = None):
 
 @cached_function    
 def Sinh(input, ddR = None):
-    from ajpastor.dd_functions.ddFunction import DDFunction;
-    if(isinstance(input, DDFunction)):
+    '''
+        DD-finite implementation of the Hyperbolic Sine function (sinh(x)).
+        
+        References:
+            - http://mathworld.wolfram.com/HyperbolicSine.html
+            - https://en.wikipedia.org/wiki/Hyperbolic_function
+            
+        This functions allows the user to fix the argument. The argument can be:
+            - A symbolic expression: all variables but "x" will be considered as parameters. Must be a polynomial expression with x as a factor.
+            - A polynomial: the first generator of the polynomial ring will be considered the variable to compute derivatives and the rest will be considered as parameters. The polynomial must be divisible by the main variable.
+            - A DDFunction: the composition will be computed. The DDFunction must have initial value 0.
+            
+        This function can be converted into symbolic expressions.
+    '''
+    if(is_DDFunction(input)):
         return Sinh(x)(input);
     f,dR = __decide_parent(input, ddR);
     
@@ -208,8 +328,21 @@ def Sinh(input, ddR = None):
 
 @cached_function    
 def Cosh(input, ddR = None):
-    from ajpastor.dd_functions.ddFunction import DDFunction;
-    if(isinstance(input, DDFunction)):
+    '''
+        DD-finite implementation of the Hyperbolic Cosine function (cosh(x)).
+        
+        References:
+            - http://mathworld.wolfram.com/HyperbolicCosine.html
+            - https://en.wikipedia.org/wiki/Hyperbolic_function
+            
+        This functions allows the user to fix the argument. The argument can be:
+            - A symbolic expression: all variables but "x" will be considered as parameters. Must be a polynomial expression with x as a factor.
+            - A polynomial: the first generator of the polynomial ring will be considered the variable to compute derivatives and the rest will be considered as parameters. The polynomial must be divisible by the main variable.
+            - A DDFunction: the composition will be computed. The DDFunction must have initial value 0.
+            
+        This function can be converted into symbolic expressions.
+    '''
+    if(is_DDFunction(input)):
         return Cosh(x)(input);
     f,dR = __decide_parent(input, ddR);
     
@@ -235,8 +368,21 @@ def Cosh(input, ddR = None):
 ##################################################################################   
 @cached_function  
 def Log(input, ddR = None):
-    from ajpastor.dd_functions.ddFunction import DDFunction;
-    if(isinstance(input, DDFunction)):
+    '''
+        DD-finite implementation of the Logarithm function (ln(x)).
+        
+        References:
+            - http://mathworld.wolfram.com/Logarithm.html
+            - https://en.wikipedia.org/wiki/Logarithm
+            
+        This functions allows the user to fix the argument. The argument can be:
+            - A symbolic expression: all variables but "x" will be considered as parameters. Must be a polynomial expression such the evaluation x=0 gives 1.
+            - A polynomial: the first generator of the polynomial ring will be considered the variable to compute derivatives and the rest will be considered as parameters. The polynomial must evaluate to 1 when the main variable is 0.
+            - A DDFunction: the composition will be computed. The DDFunction must have initial value 1.
+            
+        This function can be converted into symbolic expressions.
+    '''
+    if(is_DDFunction(input)):
         return Log(x+_sage_const_1 )(input);
     f,dR = __decide_parent(input, ddR);
     
@@ -255,8 +401,21 @@ def Log(input, ddR = None):
     
 @cached_function 
 def Log1(input, ddR = None):
-    from ajpastor.dd_functions.ddFunction import DDFunction;
-    if(isinstance(input, DDFunction)):
+    '''
+        DD-finite implementation of the shifted Logarithm function (ln(x+1)). It is equivalent to Log(input+1).
+        
+        References:
+            - http://mathworld.wolfram.com/Logarithm.html
+            - https://en.wikipedia.org/wiki/Logarithm
+            
+        This functions allows the user to fix the argument. The argument can be:
+            - A symbolic expression: all variables but "x" will be considered as parameters. Must be a polynomial expression such the evaluation x=0 gives 0.
+            - A polynomial: the first generator of the polynomial ring will be considered the variable to compute derivatives and the rest will be considered as parameters. The polynomial must evaluate to 0 when the main variable is 0.
+            - A DDFunction: the composition will be computed. The DDFunction must have initial value 0.
+            
+        This function can be converted into symbolic expressions.
+    '''
+    if(is_DDFunction(input)):
         return Log1(x)(input);
     f,dR = __decide_parent(input, ddR);
     
@@ -277,8 +436,21 @@ def Log1(input, ddR = None):
     
 @cached_function 
 def Exp(input, ddR = None):
-    from ajpastor.dd_functions.ddFunction import DDFunction;
-    if(isinstance(input, DDFunction)):
+    '''
+        DD-finite implementation of the Exponential function (exp(x)).
+        
+        References:
+            - http://mathworld.wolfram.com/ExponentialFunction.html
+            - https://en.wikipedia.org/wiki/Exponential_function
+            
+        This functions allows the user to fix the argument. The argument can be:
+            - A symbolic expression: all variables but "x" will be considered as parameters. Must be a polynomial expression such the evaluation x=0 gives 0.
+            - A polynomial: the first generator of the polynomial ring will be considered the variable to compute derivatives and the rest will be considered as parameters. The polynomial must evaluate to 0 when the main variable is 0.
+            - A DDFunction: the composition will be computed. The DDFunction must have initial value 0.
+            
+        This function can be converted into symbolic expressions.
+    '''
+    if(is_DDFunction(input)):
         return Exp(x)(input);
     f,dR = __decide_parent(input, ddR);
     
@@ -302,58 +474,119 @@ def Exp(input, ddR = None):
 ##### BESSEL TYPE FUNCTIONS
 ### Bessel Functions
 @cached_function 
-def BesselD(input, kind = _sage_const_1 ):
-    if(input is None):
-        return DDFunction_example('bessel');
-    elif(kind == _sage_const_1 ):
-        try:
-            alpha = QQ(input);
-            if(alpha < _sage_const_0 ):
-                raise ValueError("Impossible to manage Bessel functions of first kind with negative order");
-                
-            P = DFiniteP.parameters()[_sage_const_0 ];
+def BesselD(input = 'P', kind = _sage_const_1 ):
+    '''
+        DD-finite implementation of the Bessel functions (J_n(x), Y_n(x)).
+        
+        References:
+            - https://dlmf.nist.gov/10.2
+            - https://en.wikipedia.org/wiki/Bessel_function
+            - http://mathworld.wolfram.com/BesselFunction.html
             
-            func = DDFunction_example('bessel')(**{str(P):alpha});
-            if(alpha in ZZ):
-                return func.change_init_values([_sage_const_0  for i in range(alpha)] + [_sage_const_1 /_sage_const_2 **alpha, _sage_const_0 , -((alpha+_sage_const_2 )/(_sage_const_2 **(alpha+_sage_const_2 )))], name = "bessel_J(%d,x)" %input);
-            else:
-                return func.change_init_values([_sage_const_0 ], name = DinamicString("bessel_J(_1,_2)", [str(input), "x"]));
-        except TypeError:
-            raise TypeError("Impossible to manage Bessel functions of first kind with irrational order");
+        This method returns a function in the appropriate DD-Ring satisfying the differential equation
+            x^2 f'' + xf' + (x^2-P^2)f = 0
+        where 'x' is the variable and 'P' is a constant parameter (i.e. P' = 0).
+        
+        INPUT:
+            - input: the parameter 'n' for the Bessel differential equation. Currently, only non-negative integer are allowed. If no value is given, then the symbolic Bessel function (only with an equation) is returned with parameter "P". The input can also be a string with a name for the parameter or a polynomial expression involving parameters.
+            - kind: the kind of bessel function the user want to get (default 1). It can take tha values 1 or 2. Currently, only the first kind is fully implemented.
+        
+        WARNING:
+            - For power series solution this function only have non-zero solutions when the argument 'input' is a non-negative integer. Hence, initial values will also be computed for the parameter values that have power series solutions.
+            - The implementation will say that the symbolic Bessel function is the zero function for non-negative values of the parameter. In any case, the method 'to_symbolic' will return the appropriate SAGE function.
+            - When evaluating parameters, the initial values will not update and must be set by hand.
+    '''
+    parent, par = __check_list([input], DFinite.variables());
+    par = par[0];
+        
+    if(parent is QQ):
+        parent = DFinite;
     else:
-        raise ValueError("Impossible to manage Bessel functions of %dth kind" %(kind));
+        parent = ParametrizedDDRing(DFinite, [str(v) for v in parent.gens()]);
+        par = parent.base()(par);
+    x = parent.variables()[0];
+        
+    if(kind == _sage_const_1 ):
+        func = parent.element([x**2-par**2, x, x**2], name=DinamicString("bessel_J(_1,_2)", [repr(par),"x"]));
+        if(par in ZZ):
+            alpha = ZZ(par);
+            func = func.change_init_values([_sage_const_0  for i in range(alpha)] + [_sage_const_1 /_sage_const_2 **alpha, _sage_const_0 , -((alpha+_sage_const_2 )/(_sage_const_2 **(alpha+_sage_const_2 )))], name = func._DDFunction__name);
+    elif(kind == _sage_const_2 ):
+        func = parent.element([x**2-par**2, x, x**2], name=DinamicString("bessel_Y(_1,_2)", [repr(par),"x"]));
+    else:
+        raise ValueError("Impossible to manage Bessel functions of %sth kind" %(kind));
+    
+    return func;
     
 ### Struve's functions
 @cached_function
-def StruveD(mu=None,kind=1):
-    _sage_const_1 = ZZ(1); _sage_const_2 = ZZ(2); _sage_const_3 = ZZ(3);
-    if(kind != 1):
-        raise TypeError("Only struve_H functions are implemented");
+def StruveD(mu='P',kind=1):
+    '''
+        DD-finite implementation of the Struve functions (J_n(x), Y_n(x)).
         
-    f = DFinite_examples['struve'];
-    if(mu is None):
-        return f;
-    elif((mu < 0) or (mu not in ZZ)):
-        raise TypeError("Parameter must be greater or equal to -1 to have a power series (got %d)" %mu);
+        References:
+            - https://dlmf.nist.gov/11.2
+            - https://en.wikipedia.org/wiki/Struve_function
+            - http://mathworld.wolfram.com/StruveFunction.html
+            
+        Struve functions are the solutions for the inhomogeneous Bessel differential equation
+        and have also a parameter 'P' involved:
+            x^2 f'' + xf' + (x^2-P^2)f = (1/sqrt(pi)*gamma(P+1/2))*(x/2)^(P-1)
+            
+        This equation can be write as an homogeneous differential equation of order 3:
+        (1-P)*x**2+P**2*(P+1),x*(x**2-P**2-P),(2-P)*x**2,x**3
+            x^3f^(3) + (2-P)x^2f'' + x(x^2-P^2-P)f' + ((1-P)x^2 + P^3+ P^2)f = 0.
+            
+        Following the definition that we can find in the references above, we have that the Struve
+        function only have power series solutions for integers parameters greater than -1. Then the first 
+        non-zero value of the power serie has a factor of 'pi'. To avoid adding the element 'pi' to the
+        coefficients, we work with the function f_mu(x) = pi*H_mu(x).
         
-    P = f.parent().parameters()[0];
-    num = factorial(mu+_sage_const_1)*pi*(_sage_const_1/_sage_const_2)**(mu+_sage_const_1);
-    den = gamma(_sage_const_3/_sage_const_2)*gamma(mu+_sage_const_3/_sage_const_2);
-    val = QQ(num/den);
-    
-    print num,den,val;
+        INPUT:
+            - input: the parameter 'mu' for the Struve differential equation. Currently, only integers greater than -2 are allowed. If 'None' is given, then the symbolic Struve function (only with an equation) is returned with parameter "P". The input can also be a string with a name for the parameter or a polynomial expression involving parameters.
+            - kind: the kind of Struve function the user want to get (default 1). It can take the values 1 or 2. Currently, only the first kind is fully implemented.
+        
+        WARNING:
+            - Initial values will also be computed for the parameter values that have power series solutions.
+            - The implementation will say that the symbolic Bessel function is the zero function for non-negative values of the parameter. In any case, the method 'to_symbolic' will return the appropriate SAGE function.
+            - When evaluating parameters, the initial values will not update and must be set by hand.
+        
+    '''
+    parent, par = __check_list([mu], DFinite.variables());
+    par = par[0];
     
-    f = f(P=mu);
-    f = f.change_init_values([0 for i in range(mu+1)] + [val], name=f._DDFunction__name);
+    if(kind != 1):
+        raise TypeError("Only struve_H functions are implemented");
+        
+    if(parent is QQ):
+        parent = DFinite;
+    else:
+        parent = ParametrizedDDRing(DFinite, [str(v) for v in parent.gens()]);
+    f = parent.element([(1-par)*x**2+par**2*(par+1),x*(x**2-par**2-par),(2-par)*x**2,x**3], name=DinamicString("pi*struve_H(_1,_2)", [repr(par),"x"]));
+    if(par in ZZ and par >= 0):
+        num = factorial(par+_sage_const_1)*pi*(_sage_const_1/_sage_const_2)**(par+_sage_const_1);
+        den = gamma(_sage_const_3/_sage_const_2)*gamma(par+_sage_const_3/_sage_const_2);
+        val = QQ(num/den);
+        f = f.change_init_values([0 for i in range(par+1)] + [val], name=f._DDFunction__name);
     
     return f;
 
 
 ###### ORTHOGONAL POLYNOMIALS
-### Legendre Polynomials     
+### Legendre Polynomials 
 __legendre_initials = [[_sage_const_1 ,_sage_const_0 ],[_sage_const_0 ,_sage_const_1 ]];   
 @cached_function 
 def LegendreD(input):
+    '''
+        D-finite implementation of the Legendre polynomials (P_n(x))
+        
+        References:
+            - https://dlmf.nist.gov/18.3
+            - https://en.wikipedia.org/wiki/Legendre_polynomials
+            - http://mathworld.wolfram.com/LegendrePolynomial.html
+            
+        TODO
+    '''
     global __legendre_initials;
     if(input is None):
         return DDFunction_example('legendre');
@@ -378,6 +611,16 @@ def LegendreD(input):
 __chebyshev_initials = [[],[[_sage_const_1 ,_sage_const_0 ],[_sage_const_0 ,_sage_const_1 ]],[[_sage_const_1 ,_sage_const_0 ],[_sage_const_0 ,_sage_const_2 ]]];
 @cached_function    
 def ChebyshevD(input, kind = _sage_const_1 ):
+    '''
+        D-finite implementation of the Chebyshev polynomials (T_n(x), U_n(x))
+        
+        References:
+            - https://dlmf.nist.gov/18.3
+            - https://en.wikipedia.org/wiki/Chebyshev_polynomials
+            - http://mathworld.wolfram.com/ChebyshevPolynomialoftheFirstKind.html & http://mathworld.wolfram.com/ChebyshevPolynomialoftheSecondKind.html
+            
+        TODO
+    '''
     global __chebyshev_initials;
     if(input is None):
         return DDFunction_example('chebyshev%d' %kind);
@@ -413,31 +656,29 @@ def ChebyshevD(input, kind = _sage_const_1 ):
 __CACHED_HYPERGEOMETRIC = {};
 
 def HypergeometricFunction(a,b,c, init = _sage_const_1 ):
+    '''
+        D-finite implementation of the Gauss Hypergeometric function
+        
+        References:
+            - https://dlmf.nist.gov/15
+            - https://en.wikipedia.org/wiki/Hypergeometric_function
+            - http://mathworld.wolfram.com/HypergeometricFunction.html
+            
+        TODO
+    '''
     return GenericHypergeometricFunction([a,b],[c],init);
 
-def __check_list(list_of_elements, invalid_vars=[]):
-    all_vars = [];
-    for i in range(len(list_of_elements)):
-        el = list_of_elements[i];
-        if(el not in QQ):
-            if(isinstance(el, str)):
-                all_vars += [el];
-            else:
-                all_vars += [str(v) for v in el.variables()];
-                list_of_elements[i] = str(el);
-    
-    if(any(el in all_vars for el in invalid_vars)):
-        raise ValueError("An invalid variable detected in the list.\n\t- Got: %s\n\t- Invalid: %s" %(list_of_elements, invalid_vars));
-    
-    parent = QQ;
-    if(len(all_vars) > 0):
-        all_vars = list(set(all_vars));
-        parent = PolynomialRing(QQ, all_vars).fraction_field();
-        list_of_elements = [parent(el) for el in list_of_elements];
-    
-    return (parent, list_of_elements);
-
 def GenericHypergeometricFunction(num=[],den=[],init=_sage_const_1 ):
+    '''
+        D-finite implementation of the Generalized Hypergeometric Functions qFp(a_1,...,a_q;b_1,...,b_m;x)
+        
+        References:
+            - https://dlmf.nist.gov/16
+            - https://en.wikipedia.org/wiki/Generalized_hypergeometric_function
+            - http://mathworld.wolfram.com/GeneralizedHypergeometricFunction.html
+            
+        TODO
+    '''
     ## Checking arguments: num
     if (not (isinstance(num,list) or isinstance(num,set) or isinstance(num,tuple))):
         num = [num];
@@ -497,6 +738,16 @@ def GenericHypergeometricFunction(num=[],den=[],init=_sage_const_1 ):
 ### Mathieu's Functions
 @cached_function
 def MathieuD(a=None,q=None,init=()):
+    '''
+        DD-finite implementation of the Matheiu function
+        
+        References:
+            - https://dlmf.nist.gov/28.2
+            - https://en.wikipedia.org/wiki/Mathieu_function
+            - http://mathworld.wolfram.com/MathieuFunction.html
+            
+        TODO
+    '''
     params =[];
     if(a is None):
         params += ['a'];
@@ -515,15 +766,46 @@ def MathieuD(a=None,q=None,init=()):
 
 @cached_function
 def MathieuSin(a=None,q=None):
+    '''
+        DD-finite implementation of the Mathieu Sine function.
+        
+        References:
+            - https://dlmf.nist.gov/28.2
+            - https://en.wikipedia.org/wiki/Mathieu_function
+            - http://mathworld.wolfram.com/MathieuFunction.html
+            
+        This is the sine function with the Mathieu equation (i.e., with initial values
+        0 an 1). It is equivalent to MathieuD(a,q,(0,1)).
+    '''
     return MathieuD(a,q,(_sage_const_0 ,_sage_const_1 ));
     
 @cached_function
 def MathieuCos(a=None,q=None):
+    '''
+        DD-finite implementation of the Mathieu Cosine function.
+        
+        References:
+            - https://dlmf.nist.gov/28.2
+            - https://en.wikipedia.org/wiki/Mathieu_function
+            - http://mathworld.wolfram.com/MathieuFunction.html
+            
+        This is the cosine function with the Mathieu equation (i.e., with initial values
+        1 an 0). It is equivalent to MathieuD(a,q,(1,0)).
+    '''
     return MathieuD(a,q,(_sage_const_1 ,_sage_const_0 ));
 
 ### Modified Mathieu's Functions
 @cached_function
 def ModifiedMathieuD(a=None,q=None,init=()):
+    '''
+        DD-finite implementation of the Modified Matheiu functions.
+        
+        References:
+            - hhttps://dlmf.nist.gov/28.20
+            - https://en.wikipedia.org/wiki/Mathieu_function
+            
+        TODO
+    '''
     params =[];
     if(a is None):
         params += ['a'];
@@ -542,15 +824,45 @@ def ModifiedMathieuD(a=None,q=None,init=()):
 
 @cached_function
 def ModifiedMathieuSin(a=None,q=None):
+    '''
+        DD-finite implementation of the Modified Matheiu functions.
+        
+        References:
+            - hhttps://dlmf.nist.gov/28.20
+            - https://en.wikipedia.org/wiki/Mathieu_function
+            
+        This is the sine function with the Mathieu equation (i.e., with initial values
+        0 an 1). It is equivalent to ModifiedMathieuD(a,q,(0,1)).
+    '''
     return ModifiedMathieuD(a,q,(_sage_const_0 ,_sage_const_1 ));
     
 @cached_function
 def ModifiedMathieuCos(a=None,q=None):
+    '''
+        DD-finite implementation of the Modified Matheiu functions.
+        
+        References:
+            - hhttps://dlmf.nist.gov/28.20
+            - https://en.wikipedia.org/wiki/Mathieu_function
+            
+        This is the cosine function with the Mathieu equation (i.e., with initial values
+        1 an 0). It is equivalent to ModifiedMathieuD(a,q,(1,0)).
+    '''
     return ModifiedMathieuD(a,q,(_sage_const_1 ,_sage_const_0 ));
 
 ### Hill's equation
 @cached_function
 def HillD(a=None,q=None,init=()):
+    '''
+        DD-finite implementation of the Hill equation.
+        
+        References:
+            - https://dlmf.nist.gov/28.29
+            - https://en.wikipedia.org/wiki/Hill_differential_equation
+            - http://mathworld.wolfram.com/HillsDifferentialEquation.html
+            
+        TODO
+    '''
     params =[];
     destiny_ring = DFinite;
     
@@ -577,6 +889,16 @@ def HillD(a=None,q=None,init=()):
 ### Airy's functions
 @cached_function
 def AiryD(init=()):
+    '''
+        D-finite implementation of the Airy's functions (Ai(x), Bi(x)).
+        
+        References:
+            - https://dlmf.nist.gov/9.2
+            - https://en.wikipedia.org/wiki/Airy_function
+            - http://mathworld.wolfram.com/AiryFunctions.html
+            
+        TODO
+    '''
     name = None;
     if(len(init) >= 2): ## Complete Airy function, we can build the name
         ## Rejecting the zero case
@@ -606,6 +928,16 @@ def AiryD(init=()):
 ### Parabolic Cylinder Functions
 @cached_function
 def ParabolicCylinderD(a=None,b=None,c=None, init=()):
+    '''
+        D-finite implementation of Parabolic Cylinder functions.
+        
+        References:
+            - https://dlmf.nist.gov/12.2
+            - https://en.wikipedia.org/wiki/Parabolic_cylinder_function
+            - http://mathworld.wolfram.com/ParabolicCylinderDifferentialEquation.html
+            
+        TODO
+    '''
     params =[];
     if(a is None):
         params += ['a'];
@@ -617,25 +949,27 @@ def ParabolicCylinderD(a=None,b=None,c=None, init=()):
     destiny_ring = DFinite; ra = a; rb = b; rc = c;
     if(len(params) > _sage_const_0 ):
         destiny_ring = ParametrizedDDRing(DFinite, params);
-        if(len(params) == 3 ):
-            ra,rb,rc = destiny_ring.parameters();
-        elif(len(params) == 2 and 'a' not in params):
-            rb,rc = destiny_ring.parameters();
-        elif(len(params) == 2 and 'b' not in params):
-            ra,rc = destiny_ring.parameters();
-        elif(len(params) == 2 and 'c' not in params):
-            ra,rb = destiny_ring.parameters();
-        elif('a' in params):
-            ra = destiny_ring.parameters()[0];
-        elif('b' in params):
-            rb = destiny_ring.parameters()[0];
-        elif('c' in params):
-            rc = destiny_ring.parameters()[0];
+        if('a' in params):
+            ra = destiny_ring.parameter('a');
+        if('b' in params):
+            rb = destiny_ring.parameter('b');
+        if('c' in params):
+            rc = destiny_ring.parameter('c');
     return destiny_ring.element([(rc+rb*x+ra*x**2),0,1], init, name=DinamicString("ParabolicCylinder(_1,_2,_3;_4)", [repr(ra), repr(rb), repr(rc), "x"]));
     
 ###### ELLIPTIC INTEGRALS
 ## Legendre elliptic integrals
 def EllipticLegendreD(kind,var='phi'):
+    '''
+        DD-finite implementation of the Legendre elliptic integrals (F(phi,k), E(phi,k), D(phi,k)
+        
+        References:
+            - https://dlmf.nist.gov/19.2
+            - https://en.wikipedia.org/wiki/Legendre_form
+            - http://mathworld.wolfram.com/EllipticIntegraloftheFirstKind.html & http://mathworld.wolfram.com/EllipticIntegraloftheSecondKind.html & http://mathworld.wolfram.com/EllipticIntegraloftheThirdKind.html
+            
+        TODO
+    '''
     if(kind not in [0,1,2]):
         raise ValueError("The kind of legendre elliptic integral is not valid. Required 0,1 or 2");
     if(str(var) not in ['m','phi']):
@@ -665,6 +999,194 @@ def EllipticLegendreD(kind,var='phi'):
             return DDFiniteP.element([0,P**2*s*c,1-P**2*s**2], [0,1], name=name);
         else:
             return (EllipticLegendreD(1,var)-EllipticLegendreD(2,var))/P**2;
+        
+###### SPHEROIDAL WAVE FUNCTIONS
+## Generalized (or Coulomb) Spheroidal Differential Equation
+@cached_function
+def CoulombSpheroidalFunctionD(a=None, b=None, c=None, d=None, kind = 1, init=()):
+    '''
+        D-finite implementation of the Coulomb speroidal function 
+        
+        References:
+            - https://dlmf.nist.gov/30.12
+            
+        TODO
+    '''
+    if(kind not in [1,2]):
+        raise TypeValue("Generalized Spheroidal functions only allowed in two different generalizations (1 or 2). Got %s" %kind);
+    params =[];
+    if(a is None):
+        params += ['a'];
+    if(b is None):
+        params += ['b'];
+    if(c is None):
+        params += ['c'];
+    if(d is None):
+        params += ['d'];
+    
+    destiny_ring = DFinite; ra = a; rb = b; rc = c; rd = d;
+    if(len(params) > _sage_const_0 ):
+        destiny_ring = ParametrizedDDRing(DFinite, params);
+        if('a' in params):
+            ra = destiny_ring.parameter('a');
+        if('b' in params):
+            rb = destiny_ring.parameter('b');
+        if('c' in params):
+            rc = destiny_ring.parameter('c');
+        if('d' in params):
+            rd = destiny_ring.parameter('d');
+    
+    coeffs = [ra*(1-x**2)**2-(rb*(1-x**2))**2-rc**2, -2*x*(1-x**2), (1-x**2)**2];
+    if(kind == 1):
+        coeffs[0] += rd*x*(1-x**2);
+    else:
+        coeffs = [el*x**2 for el in coeffs];
+        coeffs[0] -= rd*(rd+1)*(1-x**2);
+    return destiny_ring.element(coeffs, init, name=DinamicString("CoulombSpheroidal(_1,_2,_3,_4;%d;%s)(_5)" %(kind,init), [repr(ra), repr(rb), repr(rc), repr(rd), "x"]));
+
+@cached_function
+def SpheroidalWaveFunctionD(a=None, b=None, c=None, init=()):
+    '''
+        D-finite implementation of the spheroidal wave function.
+        
+        References:
+            - https://dlmf.nist.gov/30.2
+            - https://en.wikipedia.org/wiki/Spheroidal_wave_function
+            - http://mathworld.wolfram.com/SpheroidalWaveFunction.html
+            
+        TODO
+    '''
+    params =[];
+    if(a is None):
+        params += ['a'];
+    if(b is None):
+        params += ['b'];
+    if(c is None):
+        params += ['c'];
+    
+    destiny_ring = DFinite; ra = a; rb = b; rc = c;
+    if(len(params) > _sage_const_0 ):
+        destiny_ring = ParametrizedDDRing(DFinite, params);
+        if('a' in params):
+            ra = destiny_ring.parameter('a');
+        if('b' in params):
+            rb = destiny_ring.parameter('b');
+        if('c' in params):
+            rc = destiny_ring.parameter('c');
+    
+    coeffs = [ra*(1-x**2)**2-(rb*(1-x**2))**2-rc**2, -2*x*(1-x**2), (1-x**2)**2];
+    return destiny_ring.element(coeffs, init, name=DinamicString("SpheroidalWave(_1,_2,_3;%s)(_4)" %(str(init)), [repr(ra), repr(rb), repr(rc), "x"]));
+
+###### HEUN FUNCTIONS
+### Fuschian equation
+def FuschianD(a = [], gamma = [], q = [], init=()):
+    '''
+        D-finite implementation of the Fuschian equation
+        
+        References:
+            - https://dlmf.nist.gov/31.15
+            
+        TODO
+    '''
+    ## Checking parameters
+    if (not (isinstance(a,list) or isinstance(a,set) or isinstance(a,tuple))):
+        a = [a];
+    if (not (isinstance(gamma,list) or isinstance(gamma,set) or isinstance(gamma,tuple))):
+        gamma = [gamma];
+    if (not (isinstance(q,list) or isinstance(q,set) or isinstance(q,tuple))):
+        q = [q];
+    if(len(a) == 0 or len(a) != len(gamma) or len(a) != len(q)):
+        raise ValueError("The three arguments a, gamma and q must be non-empty lists of the same length");
+    N = len(a);
+    
+    ## Getting the parameters
+    parent, new_all = __check_list(a+gamma+q, [str(el) for el in DFinite.variables()]);
+    
+    a = new_all[:N];
+    gamma = new_all[N:2*N];
+    q = new_all[-N:];
+    
+    if(sum(q) != 0):
+        raise ValueError("The q parameters must sum up zero. Got %s" %(sum(q)));
+    
+    if(parent != QQ):
+        destiny_ring = ParametrizedDDRing(DFinite, [str(v) for v in parent.gens()]);
+    else:
+        destiny_ring = DFinite;
+        
+    a = [destiny_ring.base()(el) for el in a];
+    gamma = [destiny_ring.base()(el) for el in gamma];
+    q = [destiny_ring.base()(el) for el in q];
+    x = destiny_ring.variables()[0];
+    ## Computing the differential equation
+    P = prod([x-a[i] for i in range(N)]); R = P.parent();
+    Q = [R(P/(x-a[i])) for i in range(N)];
+    
+    coeffs = [sum(q[i]*Q[i] for i in range(N)), sum(gamma[i]*Q[i] for i in range(N)), P];
+    
+    ## Returning the solution
+    return destiny_ring.element(coeffs, init, name=DinamicString("Fuschian(_1;_2;_3;%s)(_4)" %(str(init)), [repr(a), repr(gamma), repr(q), "x"]));
+
+### Heun's function
+def HeunD(a=None,b=None,d=None,g=None,e=None,q=None):
+    '''
+        D-finite implementation of the Heun's functions.
+        
+        References:
+            - https://dlmf.nist.gov/31.2
+            - https://en.wikipedia.org/wiki/Heun_function
+            - http://mathworld.wolfram.com/HeunsDifferentialEquation.html
+            
+        TODO
+    '''
+    pars = ["a","b","d","g","e","q"];
+    args = [a,b,d,g,e,q];
+    for i in range(len(args)):
+        if(args[i] is not None):
+            pars[i] = args[i];
+        
+    parent, new_all = __check_list(pars, [str(el) for el in DFinite.variables()]);
+    ra,rb,rd,rg,re,rq = new_all;
+        
+    al = rg+rd+re-rb-1;
+    f = FuschianD(a=[0,1,ra],gamma=[rd,rg,re],q=[-rq/ra,(rq-al*rb)/(ra-1), (rq/ra)-((rq-al*rb)/(ra-1))]);
+    f._DDFunction__name = DinamicString("Heun(_1,_2,_3,_4,_5,_6)(_7)", [repr(ra),repr(rb),repr(rd),repr(rg),repr(re),repr(rq),"x"]);
+    return f;
+
+###### COULOMB FUNCTIONS
+def CoulombF(m=None, l=None):
+    '''
+        D-finite implementation of the regular Coulomb wave function (F_l(mu,ro)).
+        
+        References:
+            - https://dlmf.nist.gov/33.2
+            - https://en.wikipedia.org/wiki/Coulomb_wave_function
+            
+        TODO
+    '''
+    params =[];
+    if(m is None):
+        params += ['m'];
+    if(l is None):
+        params += ['l'];
+    destiny_ring = DFinite; rm = m; rl = l;
+    if(len(params) > _sage_const_0 ):
+        destiny_ring = ParametrizedDDRing(DFinite, params);
+        if('m' in params):
+            rm = destiny_ring.parameter('m');
+        if('l' in params):
+            rl = destiny_ring.parameter('l');
+    x = destiny_ring.variables()[0];
+    init = [];
+    
+    if(l in ZZ): ## Power series solution
+        if(l in [-1,0]): ## Special cases
+            init = [0,1];
+        elif(l > 0):
+            init = [0 for i in range(l+1)] + [1];
+            
+    return destiny_ring.element([x**2-2*rm*x-rl*(rl+1), 0, x**2], init=init, name=DinamicString("CoulombF(_1;_2)(_3)", [repr(rm), repr(rl), "x"]));
+
             
 ##################################################################################
 ##################################################################################
@@ -809,20 +1331,7 @@ def DAlgebraic(polynomial, init=[], dR=None):
     ## Returning the DDFunction
     ##################################################
     return destiny_ring.element(equation, init);
-    
-##################################################################################
-##################################################################################
-###
-### Particular differential Equations
-###
-##################################################################################
-##################################################################################  
-### Federschwinger // Swing with mass
-## f'' + 2a f' + b^2f = ksin(cx)
-@cached_function
-def Federschwinger(a,b,c,k,init=(_sage_const_0 ,_sage_const_0 )):
-    return DDFinite.element([b**_sage_const_2 ,_sage_const_2 *a,_sage_const_1 ], init, k*Sin(c*x));
-    
+  
 ##################################################################################
 ##################################################################################
 ###
@@ -831,6 +1340,9 @@ def Federschwinger(a,b,c,k,init=(_sage_const_0 ,_sage_const_0 )):
 ##################################################################################
 ##################################################################################    
 def __decide_parent(input, parent = None, depth = 1):
+    '''            
+        TODO
+    '''
     if(parent is None):
         R = input.parent();
         if(isinstance(R, sage.symbolic.ring.SymbolicRing)):
@@ -852,6 +1364,36 @@ def __decide_parent(input, parent = None, depth = 1):
                 raise TypeError("The object provided is not in a valid Parent", e);
     
     return parent.base()(input), parent;
+
+def __check_list(list_of_elements, invalid_vars=[]):
+    '''
+        TODO
+    '''
+    all_vars = [];
+    for i in range(len(list_of_elements)):
+        el = list_of_elements[i];
+        if(el not in QQ):
+            if(isinstance(el, str)):
+                all_vars += [el];
+            else:
+                from sage.rings.fraction_field import is_FractionField;
+                if(is_FractionField(el.parent())):
+                    all_vars += [str(v) for v in el.numerator().variables()];
+                    all_vars += [str(v) for v in el.denominator().variables()];
+                else:
+                    all_vars += [str(v) for v in el.variables()];
+                list_of_elements[i] = str(el);
+    
+    if(any(el in all_vars for el in invalid_vars)):
+        raise ValueError("An invalid variable detected in the list.\n\t- Got: %s\n\t- Invalid: %s" %(list_of_elements, invalid_vars));
+    
+    parent = QQ;
+    if(len(all_vars) > 0):
+        all_vars = list(set(all_vars));
+        parent = PolynomialRing(QQ, all_vars).fraction_field();
+        list_of_elements = [parent(el) for el in list_of_elements];
+    
+    return (parent, list_of_elements);
     
 #### Usual running after defining everything
 DD_EXAMPLES_LOAD();
index c712ec8..d90ecf1 100644 (file)
@@ -64,6 +64,9 @@ def _aux_derivation(p):
 #####################################################
 ### Class for DD-Rings
 #####################################################
+def is_DDRing(ring):
+    return isinstance(ring, DDRing);
+
 class DDRing (Ring_w_Sequence, IntegralDomain):
     Element = None;
     
@@ -698,6 +701,9 @@ class DDRing (Ring_w_Sequence, IntegralDomain):
 ### Ring class for Parametrized DD Functions
 ###
 #############################################################################
+def is_ParametrizedDDRing(ring):
+    return isinstance(ring, ParametrizedDDRing);
+
 class ParametrizedDDRing(DDRing):
 
     @staticmethod
@@ -879,6 +885,9 @@ class ParametrizedDDRing(DDRing):
 #####################################################
 ### Class for DD-Functions
 #####################################################
+def is_DDFunction(func):
+    return isinstance(func, DDFunction);
+
 class DDFunction (IntegralDomainElement):
     #####################################
     ### Init and Interface methods
@@ -2628,6 +2637,6 @@ DFinite._DDRing__get_recurrence = __get_recurrence;
 ###################################################################################################
 ### PACKAGE ENVIRONMENT VARIABLES
 ###################################################################################################
-__all__ = ["DDRing", "DFinite", "DDFinite", "command", "zero_extraction", "polynomial_computation", "ParametrizedDDRing", "DFiniteP"];
+__all__ = ["is_DDRing", "is_ParametrizedDDRing", "is_DDFunction", "DDRing", "DFinite", "DDFinite", "command", "zero_extraction", "polynomial_computation", "ParametrizedDDRing", "DFiniteP"];
   
 
index b255822..3509c98 100644 (file)
Binary files a/releases/diff_defined_functions__0.5.zip and b/releases/diff_defined_functions__0.5.zip differ
diff --git a/releases/old/diff_defined_functions__0.5__18.09.11_17:24:39.zip b/releases/old/diff_defined_functions__0.5__18.09.11_17:24:39.zip
new file mode 100644 (file)
index 0000000..3509c98
Binary files /dev/null and b/releases/old/diff_defined_functions__0.5__18.09.11_17:24:39.zip differ