a
    <bH                     @   s  d Z ddlmZmZmZmZmZmZmZm	Z	m
Z
 ddlmZ ddlmZ ddlmZ ddlmZ ddlmZmZ ddlmZ dd	lmZmZ dd
lmZ edZedZedZedZ edZ!edZ"G dd deZ#G dd deZ$dd Z%G dd deZ&G dd deZ'G dd deZ(G dd deZ)G dd  d eZ*G d!d" d"eZ+G d#d$ d$eZ,G d%d& d&eZ-e- Z.d'd( Z/e/d)Z0d[d+d*d*d,d-d.Z1d/d0 Z2d1d2 Z3d\d3d4Z4d]d5d6Z5d^d7d8Z6d_d9d:Z7d`d;d<Z8dad=d>Z9G d?d@ d@eZ:G dAdB dBeZ;G dCdD dDeZ<G dEdF dFe<Z=G dGdH dHe<Z>G dIdJ dJe<Z?G dKdL dLe<Z@G dMdN dNe<ZAG dOdP dPe=ZBG dQdR dReZCG dSdT dTeCZDG dUdV dVeCZEG dWdX dXeeZFG dYdZ dZeeZGd*S )bz
AST nodes specific to Fortran.

The functions defined in this module allows the user to express functions such as ``dsign``
as a SymPy function for symbolic manipulation.
    )		Attribute	CodeBlockFunctionCallNodenoneStringToken	_mk_TupleVariable)BasicTuple)Expr)Function)FloatInteger)sympifytruefalse)iterablepure	elemental	intent_in
intent_outintent_inoutallocatablec                   @   s$   e Zd ZdZdZeZedd ZdS )Programaf   Represents a 'program' block in Fortran.

    Examples
    ========

    >>> from sympy.codegen.ast import Print
    >>> from sympy.codegen.fnodes import Program
    >>> prog = Program('myprogram', [Print([42])])
    >>> from sympy import fcode
    >>> print(fcode(prog, source_format='free'))
    program myprogram
        print *, 42
    end program

    )namebodyc                 C   s   t |  S Nr   r    r#   d/Users/vegardjervell/Documents/master/model/venv/lib/python3.9/site-packages/sympy/codegen/fnodes.py<lambda>2       zProgram.<lambda>N)	__name__
__module____qualname____doc__	__slots__r   _construct_namestaticmethod_construct_bodyr#   r#   r#   r$   r       s   r   c                   @   s   e Zd ZdZdZeZeZdS )
use_renamea   Represents a renaming in a use statement in Fortran.

    Examples
    ========

    >>> from sympy.codegen.fnodes import use_rename, use
    >>> from sympy import fcode
    >>> ren = use_rename("thingy", "convolution2d")
    >>> print(fcode(ren, source_format='free'))
    thingy => convolution2d
    >>> full = use('signallib', only=['snr', ren])
    >>> print(fcode(full, source_format='free'))
    use signallib, only: snr, thingy => convolution2d

    )localoriginalN)r'   r(   r)   r*   r+   r   Z_construct_localZ_construct_originalr#   r#   r#   r$   r/   5   s   r/   c                 C   s   t | dr| jS t| S d S )Nr   )hasattrr   r   argr#   r#   r$   _nameI   s    
r5   c                   @   s>   e Zd ZdZdZeedZeeZ	edd Z
edd ZdS )usea   Represents a use statement in Fortran.

    Examples
    ========

    >>> from sympy.codegen.fnodes import use
    >>> from sympy import fcode
    >>> fcode(use('signallib'), source_format='free')
    'use signallib'
    >>> fcode(use('signallib', [('metric', 'snr')]), source_format='free')
    'use signallib, metric => snr'
    >>> fcode(use('signallib', only=['snr', 'convolution2d']), source_format='free')
    'use signallib, only: snr, convolution2d'

    )	namespacerenameonly)r8   r9   c                 C   s   t dd | D  S )Nc                 S   s"   g | ]}t |tr|nt| qS r#   )
isinstancer/   .0r4   r#   r#   r$   
<listcomp>b   r&    use.<lambda>.<locals>.<listcomp>r   argsr#   r#   r$   r%   b   r&   zuse.<lambda>c                 C   s   t dd | D  S )Nc                 S   s"   g | ]}t |tr|nt|qS r#   )r:   r/   r5   r;   r#   r#   r$   r=   c   r&   r>   r   r?   r#   r#   r$   r%   c   r&   N)r'   r(   r)   r*   r+   r   defaultsr-   r5   Z_construct_namespaceZ_construct_renameZ_construct_onlyr#   r#   r#   r$   r6   O   s   
r6   c                   @   s:   e Zd ZdZdZde iZeZe	dd Z
e	dd ZdS )Modulea\   Represents a module in Fortran.

    Examples
    ========

    >>> from sympy.codegen.fnodes import Module
    >>> from sympy import fcode
    >>> print(fcode(Module('signallib', ['implicit none'], []), source_format='free'))
    module signallib
    implicit none
    <BLANKLINE>
    contains
    <BLANKLINE>
    <BLANKLINE>
    end module

    )r   declarationsZdefinitionsrC   c                 C   s   t |  S r    r!   r3   r#   r#   r$   r%   {   r&   zModule.<lambda>c                 C   s   t |  S r    r!   r3   r#   r#   r$   r%   |   r&   N)r'   r(   r)   r*   r+   r   rA   r   r,   r-   Z_construct_declarationsZ_construct_definitionsr#   r#   r#   r$   rB   f   s   
rB   c                   @   s0   e Zd ZdZdZeZedd Ze	dd Z
dS )
Subroutinea   Represents a subroutine in Fortran.

    Examples
    ========

    >>> from sympy import fcode, symbols
    >>> from sympy.codegen.ast import Print
    >>> from sympy.codegen.fnodes import Subroutine
    >>> x, y = symbols('x y', real=True)
    >>> sub = Subroutine('mysub', [x, y], [Print([x**2 + y**2, x*y])])
    >>> print(fcode(sub, source_format='free', standard=2003))
    subroutine mysub(x, y)
    real*8 :: x
    real*8 :: y
    print *, x**2 + y**2, x*y
    end subroutine

    )r   
parametersr   attrsc                 C   s   t ttj|  S r    )r   mapr
   deduced)paramsr#   r#   r$   r%      r&   zSubroutine.<lambda>c                 C   s   t |tr|S t| S d S r    )r:   r   )clsitrr#   r#   r$   r.      s    
zSubroutine._construct_bodyN)r'   r(   r)   r*   r+   r   r,   r-   Z_construct_parametersclassmethodr.   r#   r#   r#   r$   rD      s   rD   c                   @   s$   e Zd ZdZdZeeZeeZ	dS )SubroutineCallz Represents a call to a subroutine in Fortran.

    Examples
    ========

    >>> from sympy.codegen.fnodes import SubroutineCall
    >>> from sympy import fcode
    >>> fcode(SubroutineCall('mysub', 'x y'.split()))
    '       call mysub(x, y)'

    )r   Zsubroutine_argsN)
r'   r(   r)   r*   r+   r-   r5   r,   r	   Z_construct_subroutine_argsr#   r#   r#   r$   rM      s   rM   c                   @   sZ   e Zd ZdZdZededZedd Z	ee
Zee
Zee
Zee
Zedd ZdS )	Doa   Represents a Do loop in in Fortran.

    Examples
    ========

    >>> from sympy import fcode, symbols
    >>> from sympy.codegen.ast import aug_assign, Print
    >>> from sympy.codegen.fnodes import Do
    >>> i, n = symbols('i n', integer=True)
    >>> r = symbols('r', real=True)
    >>> body = [aug_assign(r, '+', 1/i), Print([i, r])]
    >>> do1 = Do(body, i, 1, n)
    >>> print(fcode(do1, source_format='free'))
    do i = 1, n
        r = r + 1d0/i
        print *, i, r
    end do
    >>> do2 = Do(body, i, 1, n, 2)
    >>> print(fcode(do2, source_format='free'))
    do i = 1, n, 2
        r = r + 1d0/i
        print *, i, r
    end do

    )r   counterfirstlaststep
concurrent   )rR   rS   c                 C   s   t |  S r    r!   r"   r#   r#   r$   r%      r&   zDo.<lambda>c                 C   s   | rt S tS r    r   r3   r#   r#   r$   r%      r&   N)r'   r(   r)   r*   r+   r   r   rA   r-   r.   r   _construct_counter_construct_first_construct_last_construct_stepZ_construct_concurrentr#   r#   r#   r$   rN      s   rN   c                   @   s   e Zd ZdZdZeeZdS )ArrayConstructoraT   Represents an array constructor.

    Examples
    ========

    >>> from sympy import fcode
    >>> from sympy.codegen.fnodes import ArrayConstructor
    >>> ac = ArrayConstructor([1, 2, 3])
    >>> fcode(ac, standard=95, source_format='free')
    '(/1, 2, 3/)'
    >>> fcode(ac, standard=2003, source_format='free')
    '[1, 2, 3]'

    )elementsN)r'   r(   r)   r*   r+   r-   r	   Z_construct_elementsr#   r#   r#   r$   rY      s   rY   c                   @   sH   e Zd ZdZdZdediZeeZ	eeZ
eeZeeZeeZdS )ImpliedDoLoopa   Represents an implied do loop in Fortran.

    Examples
    ========

    >>> from sympy import Symbol, fcode
    >>> from sympy.codegen.fnodes import ImpliedDoLoop, ArrayConstructor
    >>> i = Symbol('i', integer=True)
    >>> idl = ImpliedDoLoop(i**3, i, -3, 3, 2)  # -27, -1, 1, 27
    >>> ac = ArrayConstructor([-28, idl, 28]) # -28, -27, -1, 1, 27, 28
    >>> fcode(ac, standard=2003, source_format='free')
    '[-28, (i**3, i = -3, 3, 2), 28]'

    )exprrO   rP   rQ   rR   rR   rT   N)r'   r(   r)   r*   r+   r   rA   r-   r   _construct_exprrU   rV   rW   rX   r#   r#   r#   r$   r[      s   r[   c                   @   s    e Zd ZdZdd Zdd ZdS )ExtentaC   Represents a dimension extent.

    Examples
    ========

    >>> from sympy.codegen.fnodes import Extent
    >>> e = Extent(-3, 3)  # -3, -2, -1, 0, 1, 2, 3
    >>> from sympy import fcode
    >>> fcode(e, source_format='free')
    '-3:3'
    >>> from sympy.codegen.ast import Variable, real
    >>> from sympy.codegen.fnodes import dimension, intent_out
    >>> dim = dimension(e, e)
    >>> arr = Variable('x', real, attrs=[dim, intent_out])
    >>> fcode(arr.as_Declaration(), source_format='free', standard=2003)
    'real*8, dimension(-3:3, -3:3), intent(out) :: x'

    c                 G   sd   t |dkr*|\}}t| t|t|S t |dksNt |dkrX|d dv rXt| S tdd S )N   r   rT   ):Nz5Expected 0 or 2 args (or one argument == None or ':'))lenr   __new__r   
ValueError)rJ   r@   lowhighr#   r#   r$   rb     s    $
zExtent.__new__c                 C   s(   t | jdkrdS ddd | jD S )Nr   r`   c                 s   s   | ]}t |V  qd S r    )strr;   r#   r#   r$   	<genexpr>  r&   z#Extent._sympystr.<locals>.<genexpr>)ra   r@   join)selfprinterr#   r#   r$   	_sympystr  s    zExtent._sympystrN)r'   r(   r)   r*   rb   rk   r#   r#   r#   r$   r^      s   	r^   c                  G   s   t | dkrtdg }| D ]p}t|tr6|| qt|trf|dkrV|t  q|t| qt|r~|t|  q|t| qt | dkrtdt	d|S )a   Creates a 'dimension' Attribute with (up to 7) extents.

    Examples
    ========

    >>> from sympy import fcode
    >>> from sympy.codegen.fnodes import dimension, intent_in
    >>> dim = dimension('2', ':')  # 2 rows, runtime determined number of columns
    >>> from sympy.codegen.ast import Variable, integer
    >>> arr = Variable('a', integer, attrs=[dim, intent_in])
    >>> fcode(arr.as_Declaration(), source_format='free', standard=2003)
    'integer*4, dimension(2, :), intent(in) :: a'

       z0Fortran only supports up to 7 dimensional arraysr`   r   zNeed at least one dimension	dimension)
ra   rc   r:   r^   appendrf   r   r   r   r   )r@   rE   r4   r#   r#   r$   rm   "  s     

rm   *Nr#   )rF   valuetypec                C   s   t |tr*t|jdkr2tdt| nt| }t||g }|durp|ttt	fvrfttt	d| }|
| |du rtj| ||dS t| |||dS dS )a   Convenience function for creating a Variable instance for a Fortran array.

    Parameters
    ==========

    symbol : symbol
    dim : Attribute or iterable
        If dim is an ``Attribute`` it need to have the name 'dimension'. If it is
        not an ``Attribute``, then it is passsed to :func:`dimension` as ``*dim``
    intent : str
        One of: 'in', 'out', 'inout' or None
    \*\*kwargs:
        Keyword arguments for ``Variable`` ('type' & 'value')

    Examples
    ========

    >>> from sympy import fcode
    >>> from sympy.codegen.ast import integer, real
    >>> from sympy.codegen.fnodes import array
    >>> arr = array('a', '*', 'in', type=integer)
    >>> print(fcode(arr.as_Declaration(), source_format='free', standard=2003))
    integer*4, dimension(*), intent(in) :: a
    >>> x = array('x', [3, ':', ':'], intent='out', type=real)
    >>> print(fcode(x.as_Declaration(value=1), source_format='free', standard=2003))
    real*8, dimension(3, :, :), intent(out) :: x = 1

    rm   z/Got an unexpected Attribute argument as dim: %sN)inoutZinout)rp   rF   )r:   r   rf   r   rc   rm   listr   r   r   rn   r
   rH   )symboldimZintentrF   rp   rq   r#   r#   r$   arrayG  s    

rw   c                 C   s   t | trt| S t| S r    )r:   rf   r   r   r3   r#   r#   r$   
_printablet  s    rx   c                 C   s   t dt| gS )a   Creates an AST node for a function call to Fortran's "allocated(...)"

    Examples
    ========

    >>> from sympy import fcode
    >>> from sympy.codegen.fnodes import allocated
    >>> alloc = allocated('x')
    >>> fcode(alloc, source_format='free')
    'allocated(x)'

    	allocatedr   rx   )rw   r#   r#   r$   ry   x  s    ry   c                 C   s4   t dt| g|rt|gng  |r,t|gng  S )ap   Creates an AST node for a function call to Fortran's "lbound(...)"

    Parameters
    ==========

    array : Symbol or String
    dim : expr
    kind : expr

    Examples
    ========

    >>> from sympy import fcode
    >>> from sympy.codegen.fnodes import lbound
    >>> lb = lbound('arr', dim=2)
    >>> fcode(lb, source_format='free')
    'lbound(arr, 2)'

    lboundrz   rw   rv   kindr#   r#   r$   r{     s    r{   c                 C   s4   t dt| g|rt|gng  |r,t|gng  S )Nuboundrz   r|   r#   r#   r$   r~     s    r~   c                 C   s"   t dt| g|rt|gng  S )aR   Creates an AST node for a function call to Fortran's "shape(...)"

    Parameters
    ==========

    source : Symbol or String
    kind : expr

    Examples
    ========

    >>> from sympy import fcode
    >>> from sympy.codegen.fnodes import shape
    >>> shp = shape('x')
    >>> fcode(shp, source_format='free')
    'shape(x)'

    shaperz   )sourcer}   r#   r#   r$   r     s    r   c                 C   s4   t dt| g|rt|gng  |r,t|gng  S )a   Creates an AST node for a function call to Fortran's "size(...)"

    Examples
    ========

    >>> from sympy import fcode, Symbol
    >>> from sympy.codegen.ast import FunctionDefinition, real, Return
    >>> from sympy.codegen.fnodes import array, sum_, size
    >>> a = Symbol('a', real=True)
    >>> body = [Return((sum_(a**2)/size(a))**.5)]
    >>> arr = array(a, dim=[':'], intent='in')
    >>> fd = FunctionDefinition(real, 'rms', [arr], body)
    >>> print(fcode(fd, source_format='free', standard=2003))
    real*8 function rms(a)
    real*8, dimension(:), intent(in) :: a
    rms = sqrt(sum(a**2)*1d0/size(a))
    end function

    sizerz   r|   r#   r#   r$   r     s    r   c                 C   s:   t dt| t|g|r t|gng  |r2t|gng  S )z Creates an AST node for a function call to Fortran's "reshape(...)"

    Parameters
    ==========

    source : Symbol or String
    shape : ArrayExpr

    reshaperz   )r   r   padorderr#   r#   r$   r     s    
r   c                 C   s   t d| rt| gng S )a   Creates an Attribute ``bind_C`` with a name.

    Parameters
    ==========

    name : str

    Examples
    ========

    >>> from sympy import fcode, Symbol
    >>> from sympy.codegen.ast import FunctionDefinition, real, Return
    >>> from sympy.codegen.fnodes import array, sum_, bind_C
    >>> a = Symbol('a', real=True)
    >>> s = Symbol('s', integer=True)
    >>> arr = array(a, dim=[s], intent='in')
    >>> body = [Return((sum_(a**2)/s)**.5)]
    >>> fd = FunctionDefinition(real, 'rms', [arr, s], body, attrs=[bind_C('rms')])
    >>> print(fcode(fd, source_format='free', standard=2003))
    real*8 function rms(a, s) bind(C, name="rms")
    real*8, dimension(s), intent(in) :: a
    integer*4 :: s
    rms = sqrt(sum(a**2)/s)
    end function

    bind_C)r   r   )r   r#   r#   r$   r     s    r   c                   @   s,   e Zd ZdZdZdeiZeeZ	ee
ZdS )GoToa    Represents a goto statement in Fortran

    Examples
    ========

    >>> from sympy.codegen.fnodes import GoTo
    >>> go = GoTo([10, 20, 30], 'i')
    >>> from sympy import fcode
    >>> fcode(go, source_format='free')
    'go to (10, 20, 30), i'

    )labelsr\   r\   N)r'   r(   r)   r*   r+   r   rA   r-   r	   Z_construct_labelsr   r]   r#   r#   r#   r$   r     s
   r   c                   @   s$   e Zd ZdZdZdeiZeeZ	dS )FortranReturnaK   AST node explicitly mapped to a fortran "return".

    Explanation
    ===========

    Because a return statement in fortran is different from C, and
    in order to aid reuse of our codegen ASTs the ordinary
    ``.codegen.ast.Return`` is interpreted as assignment to
    the result variable of the function. If one for some reason needs
    to generate a fortran RETURN statement, this node should be used.

    Examples
    ========

    >>> from sympy.codegen.fnodes import FortranReturn
    >>> from sympy import fcode
    >>> fcode(FortranReturn('x'))
    '       return x'

    )return_valuer   N)
r'   r(   r)   r*   r+   r   rA   r-   r   Z_construct_return_valuer#   r#   r#   r$   r   %  s   r   c                   @   s   e Zd ZdZdd ZdS )	FFunctionM   c                 C   sF   | j j}|jd | jk r*td|| jf d|dt|j| j	S )Nstandardz%s requires Fortran %d or newerz{}({})z, )
	__class__r'   Z	_settings_required_standardNotImplementedErrorformatrh   rG   Z_printr@   )ri   rj   r   r#   r#   r$   _fcodeB  s    zFFunction._fcodeN)r'   r(   r)   r   r   r#   r#   r#   r$   r   ?  s   r   c                   @   s   e Zd ZdZdS )F95Function_   N)r'   r(   r)   r   r#   r#   r#   r$   r   J  s   r   c                   @   s   e Zd ZdZdZdS )isignz/ Fortran sign intrinsic for integer arguments. r_   Nr'   r(   r)   r*   nargsr#   r#   r#   r$   r   N  s   r   c                   @   s   e Zd ZdZdZdS )dsignz8 Fortran sign intrinsic for double precision arguments. r_   Nr   r#   r#   r#   r$   r   S  s   r   c                   @   s   e Zd ZdZdZdS )cmplxz& Fortran complex conversion function. r_   Nr   r#   r#   r#   r$   r   X  s   r   c                   @   s   e Zd ZdZdZdS )r}   z Fortran kind function. rT   Nr   r#   r#   r#   r$   r}   ]  s   r}   c                   @   s   e Zd ZdZdZdS )mergez Fortran merge function    Nr   r#   r#   r#   r$   r   b  s   r   c                   @   s   e Zd ZdZdZdd ZdS )_literalNc                 O   sp   d | j|  d\}}|dd}|d |dd  d }}|dkrRdn|}|p\d| j | |pld S )	Nz%.{}ee0.r   rT   + )r   	_decimalssplitstriprstriplstrip_token)ri   rj   r@   kwargsZmantissaZsgnd_exZex_sgnZex_numr#   r#   r$   r   k  s
    z_literal._fcode)r'   r(   r)   r   r   r   r#   r#   r#   r$   r   g  s   r   c                   @   s   e Zd ZdZdZdZdS )
literal_spz' Fortran single precision real literal r   	   Nr'   r(   r)   r*   r   r   r#   r#   r#   r$   r   s  s   r   c                   @   s   e Zd ZdZdZdZdS )
literal_dpz' Fortran double precision real literal d   Nr   r#   r#   r#   r$   r   y  s   r   c                   @   s*   e Zd ZdZeedZeeZeeZ	dS )sum_rw   rv   maskrv   r   N
r'   r(   r)   r+   r   rA   r-   r   Z_construct_arrayZ_construct_dimr#   r#   r#   r$   r     s   
r   c                   @   s*   e Zd ZdZeedZeeZeeZ	dS )product_r   r   Nr   r#   r#   r#   r$   r     s   
r   )N)NN)NN)N)NN)NN)N)Hr*   Zsympy.codegen.astr   r   r   r   r   r   r   r	   r
   Zsympy.core.basicr   Zsympy.core.containersr   Zsympy.core.exprr   Zsympy.core.functionr   Zsympy.core.numbersr   r   Zsympy.core.sympifyr   Zsympy.logicr   r   Zsympy.utilities.iterablesr   r   r   r   r   r   r   r   r/   r5   r6   rB   rD   rM   rN   rY   r[   r^   Zassumed_extentrm   Zassumed_sizerw   rx   ry   r{   r~   r   r   r   r   r   r   r   r   r   r   r   r}   r   r   r   r   r   r   r#   r#   r#   r$   <module>   sh   ,%!#-

	



