# Path: blond/toolbox/next_regular.py
# def next_regular(target):
#     """
#     Find the next regular number greater than or equal to target.
#     Regular numbers are composites of the prime factors 2, 3, and 5.
#     Also known as 5-smooth numbers or Hamming numbers, these are the optimal
#     size for inputs to FFTPACK.
# 
#     Target must be a positive integer.
#     """
#     if target <= 6:
#         return target
# 
#     # Quickly check if it's already a power of 2
#     if not (target & (target-1)):
#         return target
#     
#     target = -(-target // 2)
#     
#     match = float('inf') # Anything found will be smaller
#     p5 = 1
#     while p5 < target:
#         p35 = p5
#         while p35 < target:
#             # Ceiling integer division, avoiding conversion to float
#             # (quotient = ceil(target / p35))
#             quotient = -(-target // p35)
# 
#             # Quickly find next power of 2 >= quotient
#             try:
#                 p2 = 2**((quotient - 1).bit_length())
#             except AttributeError:
#                 # Fallback for Python <2.7
#                 p2 = 2**(len(bin(quotient - 1)) - 2)
# 
#             N = p2 * p35
#             if N == target:
#                 return N * 2
#             elif N < match:
#                 match = N
#             p35 *= 3
#             if p35 == target:
#                 return p35 * 2
#         if p35 < match:
#             match = p35
#         p5 *= 5
#         if p5 == target:
#             return p5 * 2
#     if p5 < match:
#         match = p5
#     
#     return match * 2


from builtins import range, object
from scipy.constants import c
from ..plots.plot import *
from ..plots.plot_llrf import *
from ..toolbox.next_regular import next_regular
import numpy as np
import numpy.random as rnd
import matplotlib.pyplot as plt
        # Multiply by desired noise probability density
        if transform==None or transform=='r':
            s = np.sqrt(2*fmax*spectrum) # in [rad]
        elif transform=='c':
            s = np.sqrt(fmax*spectrum) # in [rad]
        dPf = s*Gf.real + 1j*s*Gf.imag  # in [rad]
                
        # FFT back to time domain to get final phase shift
        if transform==None or transform=='r':
            dPt = np.fft.irfft(dPf) # in [rad]
        elif transform=='c':
            dPt = np.fft.ifft(dPf) # in [rad]
                    
        # Use only real part for the phase shift and normalize
        self.t = np.linspace(0, float(nt*dt), nt) 
        self.dphi_output = dPt.real
 
    
    def generate(self):
       
        for i in range(0, np.int(np.ceil(self.n_turns/self.corr))):
        
            # Scale amplitude to keep area (phase noise amplitude) constant
            k = i*self.corr       # current time step
            ampl = self.A_i*self.fs[0]/self.fs[k]
            
            # Calculate the frequency step
            f_max = self.f0[k]/2
            n_points_pos_f_incl_zero = int(np.ceil(f_max/self.delta_f) + 1)
            nt = 2*(n_points_pos_f_incl_zero - 1)

# Path: blond/toolbox/next_regular.py
# def next_regular(target):
#     """
#     Find the next regular number greater than or equal to target.
#     Regular numbers are composites of the prime factors 2, 3, and 5.
#     Also known as 5-smooth numbers or Hamming numbers, these are the optimal
#     size for inputs to FFTPACK.
# 
#     Target must be a positive integer.
#     """
#     if target <= 6:
#         return target
# 
#     # Quickly check if it's already a power of 2
#     if not (target & (target-1)):
#         return target
#     
#     target = -(-target // 2)
#     
#     match = float('inf') # Anything found will be smaller
#     p5 = 1
#     while p5 < target:
#         p35 = p5
#         while p35 < target:
#             # Ceiling integer division, avoiding conversion to float
#             # (quotient = ceil(target / p35))
#             quotient = -(-target // p35)
# 
#             # Quickly find next power of 2 >= quotient
#             try:
#                 p2 = 2**((quotient - 1).bit_length())
#             except AttributeError:
#                 # Fallback for Python <2.7
#                 p2 = 2**(len(bin(quotient - 1)) - 2)
# 
#             N = p2 * p35
#             if N == target:
#                 return N * 2
#             elif N < match:
#                 match = N
#             p35 *= 3
#             if p35 == target:
#                 return p35 * 2
#         if p35 < match:
#             match = p35
#         p5 *= 5
#         if p5 == target:
#             return p5 * 2
#     if p5 < match:
#         match = p5
#     
#     return match * 2


# Path: blond/llrf/rf_noise.py
from builtins import range, object
from scipy.constants import c
from ..plots.plot import *
from ..plots.plot_llrf import *
from ..toolbox.next_regular import next_regular
import numpy as np
import numpy.random as rnd
import matplotlib.pyplot as plt

        # Multiply by desired noise probability density
        if transform==None or transform=='r':
            s = np.sqrt(2*fmax*spectrum) # in [rad]
        elif transform=='c':
            s = np.sqrt(fmax*spectrum) # in [rad]
        dPf = s*Gf.real + 1j*s*Gf.imag  # in [rad]
                
        # FFT back to time domain to get final phase shift
        if transform==None or transform=='r':
            dPt = np.fft.irfft(dPf) # in [rad]
        elif transform=='c':
            dPt = np.fft.ifft(dPf) # in [rad]
                    
        # Use only real part for the phase shift and normalize
        self.t = np.linspace(0, float(nt*dt), nt) 
        self.dphi_output = dPt.real
 
    
    def generate(self):
       
        for i in range(0, np.int(np.ceil(self.n_turns/self.corr))):
        
            # Scale amplitude to keep area (phase noise amplitude) constant
            k = i*self.corr       # current time step
            ampl = self.A_i*self.fs[0]/self.fs[k]
            
            # Calculate the frequency step
            f_max = self.f0[k]/2
            n_points_pos_f_incl_zero = int(np.ceil(f_max/self.delta_f) + 1)
            nt = 2*(n_points_pos_f_incl_zero - 1)

            nt_regular = next_regular(int(nt))