U
    d»{j‰  ã                   @   s4   d dl mZ d dlZdd„ Zddd„Zddd„ZdS )é    )Ú	factorialNc                 C   s   dt | d ƒ ¡ > S )z·
    Find the bit (i.e. power of 2) immediately greater than or equal to N
    Note: this works for numbers up to 2 ** 64.
    Roughly equivalent to int(2 ** np.ceil(np.log2(N)))
    é   )ÚintÚ
bit_length)ÚN© r   ú€/var/www/html/bwave/python/venv/lib/python3.8/site-packages/astropy/timeseries/periodograms/lombscargle/implementations/utils.pyÚbitceil   s    r	   é   c              	   C   s:  t tjt | |¡ƒ\} }|dkr:tt | ¡d|  d ƒ}tj||jd�}| d dk}tj 	|| |  
t¡|| ¡ | |  ||   } }t | |d   
t¡d|| ¡}|t | | t |¡dd…tjf  d¡ }t|d ƒ}t|ƒD ]J}	|	dk�r||	|	|  9 }||d |	  }
tj 	||
||| |
   ¡ qê|S )aö  
    Extirpolate the values (x, y) onto an integer grid range(N),
    using lagrange polynomial weights on the M nearest points.

    Parameters
    ----------
    x : array-like
        array of abscissas
    y : array-like
        array of ordinates
    N : int
        number of integer bins to use. For best performance, N should be larger
        than the maximum of x
    M : int
        number of adjoining points on which to extirpolate.

    Returns
    -------
    yN : ndarray
        N extirpolated values associated with range(N)

    Examples
    --------
    >>> rng = np.random.default_rng(0)
    >>> x = 100 * rng.random(20)
    >>> y = np.sin(x)
    >>> y_hat = extirpolate(x, y)
    >>> x_hat = np.arange(len(y_hat))
    >>> f = lambda x: np.sin(x / 10)
    >>> np.allclose(np.sum(y * f(x)), np.sum(y_hat * f(x_hat)))
    True

    Notes
    -----
    This code is based on the C implementation of spread() presented in
    Numerical Recipes in C, Second Edition (Press et al. 1989; p.583).
    Ng      à?r   )Údtyper   é   )ÚmapÚnpÚravelÚbroadcast_arraysr   ÚmaxZzerosr   ÚaddÚatZastypeZclipÚprodÚarangeÚnewaxisr   Úrange)ÚxÚyr   ÚMÚresultZintegersZiloÚ	numeratorÚdenominatorÚjÚindr   r   r   Úextirpolate   s     & ,
r    r   é   Tc	              	   C   sŠ  ||9 }||9 }|dkr t dƒ‚ttjt | |¡ƒ\} }|�rt|ƒ}|dkrVt dƒ‚t|| ƒ}	|  ¡ }
|dkr’|t dtj	 | | |
  ¡ }| |
 |	 | |	 }t
|||	|ƒ}tj |¡d|… }|
dkrþ||t |¡  }|t dtj	 |
 | ¡9 }|	|j }|	|j }nn||t |¡  }t |t dtj	 | | dd…tjf  ¡¡}t |t dtj	 | | dd…tjf  ¡¡}||fS )aÓ  Compute (approximate) trigonometric sums for a number of frequencies
    This routine computes weighted sine and cosine sums::

        S_j = sum_i { h_i * sin(2 pi * f_j * t_i) }
        C_j = sum_i { h_i * cos(2 pi * f_j * t_i) }

    Where f_j = freq_factor * (f0 + j * df) for the values j in 1 ... N.
    The sums can be computed either by a brute force O[N^2] method, or
    by an FFT-based O[Nlog(N)] method.

    Parameters
    ----------
    t : array-like
        array of input times
    h : array-like
        array weights for the sum
    df : float
        frequency spacing
    N : int
        number of frequency bins to return
    f0 : float, optional
        The low frequency to use
    freq_factor : float, optional
        Factor which multiplies the frequency
    use_fft : bool
        if True, use the approximate FFT algorithm to compute the result.
        This uses the FFT with Press & Rybicki's Lagrangian extirpolation.
    oversampling : int (default = 5)
        oversampling freq_factor for the approximation; roughly the number of
        time samples across the highest-frequency sinusoid. This parameter
        contains the trade-off between accuracy and speed. Not referenced
        if use_fft is False.
    Mfft : int
        The number of adjacent points to use in the FFT approximation.
        Not referenced if use_fft is False.

    Returns
    -------
    S, C : ndarray
        summation arrays for frequencies f = df * np.arange(1, N + 1)
    r   zdf must be positivezMfft must be positivey               @Nr   )Ú
ValueErrorr   r   r   r   r   r	   ÚminÚexpÚpir    ZfftZifftr   ÚrealÚimagÚdotÚcosr   Úsin)ÚtÚhZdfr   Zf0Zfreq_factorZoversamplingZuse_fftZMfftZNfftÚt0ZtnormÚgridZfftgridÚfÚCÚSr   r   r   Útrig_sumR   s2    * 
..r2   )Nr
   )r   r   r!   Tr
   )Úmathr   Únumpyr   r	   r    r2   r   r   r   r   Ú<module>   s   	
C