text: /*
   *  Copyright (c) 2003-2010, Mark Borgerding. All rights reserved.
   *  This file is part of KISS FFT - https://github.com/mborgerding/kissfft
   *
   *  SPDX-License-Identifier: BSD-3-Clause
   *  See COPYING file for more information.
   */
  
  /* kiss_fft.h
     defines kiss_fft_scalar as either short or a float type
     and defines
     typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
  
  #ifndef _kiss_fft_guts_h
  #define _kiss_fft_guts_h
  
  #include "kiss_fft.h"
  #include "kiss_fft_log.h"
  #include <limits.h>
  
  #define MAXFACTORS 32
  /* e.g. an fft of length 128 has 4 factors
   as far as kissfft is concerned
   4*4*4*2
   */
  
  struct kiss_fft_state{
      int nfft;
      int inverse;
      int factors[2*MAXFACTORS];
      kiss_fft_cpx twiddles[1];
  };
  
  /*
    Explanation of macros dealing with complex math:
  
     C_MUL(m,a,b)         : m = a*b
     C_FIXDIV( c , div )  : if a fixed point impl., c /= div. noop otherwise
     C_SUB( res, a,b)     : res = a - b
     C_SUBFROM( res , a)  : res -= a
     C_ADDTO( res , a)    : res += a
   * */
  #ifdef FIXED_POINT
  #include <stdint.h>
  #if (FIXED_POINT==32)
  # define FRACBITS 31
  # define SAMPPROD int64_t
  #define SAMP_MAX INT32_MAX
  #define SAMP_MIN INT32_MIN
  #else
  # define FRACBITS 15
  # define SAMPPROD int32_t
  #define SAMP_MAX INT16_MAX
  #define SAMP_MIN INT16_MIN
  #endif
  
  #if defined(CHECK_OVERFLOW)
  #  define CHECK_OVERFLOW_OP(a,op,b)  \
      if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
          KISS_FFT_WARNING("overflow (%d " #op" %d) = %ld", (a),(b),(SAMPPROD)(a) op (SAMPPROD)(b)); }
  #endif
  
  
  #   define smul(a,b) ( (SAMPPROD)(a)*(b) )
  #   define sround( x )  (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS )
  
  #   define S_MUL(a,b) sround( smul(a,b) )
  
  #   define C_MUL(m,a,b) \
        do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
            (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
  
  #   define DIVSCALAR(x,k) \
      (x) = sround( smul(  x, SAMP_MAX/k ) )
  
  #   define C_FIXDIV(c,div) \
      do {    DIVSCALAR( (c).r , div);  \
          DIVSCALAR( (c).i  , div); }while (0)
  
  #   define C_MULBYSCALAR( c, s ) \
      do{ (c).r =  sround( smul( (c).r , s ) ) ;\
          (c).i =  sround( smul( (c).i , s ) ) ; }while(0)
  
  #else  /* not FIXED_POINT*/
  
  #   define S_MUL(a,b) ( (a)*(b) )
  #define C_MUL(m,a,b) \
      do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
          (m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
  #   define C_FIXDIV(c,div) /* NOOP */
  #   define C_MULBYSCALAR( c, s ) \
      do{ (c).r *= (s);\
          (c).i *= (s); }while(0)
  #endif
  
  #ifndef CHECK_OVERFLOW_OP
  #  define CHECK_OVERFLOW_OP(a,op,b) /* noop */
  #endif
  
  #define  C_ADD( res, a,b)\
      do { \
          CHECK_OVERFLOW_OP((a).r,+,(b).r)\
          CHECK_OVERFLOW_OP((a).i,+,(b).i)\
          (res).r=(a).r+(b).r;  (res).i=(a).i+(b).i; \
      }while(0)
  #define  C_SUB( res, a,b)\
      do { \
          CHECK_OVERFLOW_OP((a).r,-,(b).r)\
          CHECK_OVERFLOW_OP((a).i,-,(b).i)\
          (res).r=(a).r-(b).r;  (res).i=(a).i-(b).i; \
      }while(0)
  #define C_ADDTO( res , a)\
      do { \
          CHECK_OVERFLOW_OP((res).r,+,(a).r)\
          CHECK_OVERFLOW_OP((res).i,+,(a).i)\
          (res).r += (a).r;  (res).i += (a).i;\
      }while(0)
  
  #define C_SUBFROM( res , a)\
      do {\
          CHECK_OVERFLOW_OP((res).r,-,(a).r)\
          CHECK_OVERFLOW_OP((res).i,-,(a).i)\
          (res).r -= (a).r;  (res).i -= (a).i; \
      }while(0)
  
  
  #ifdef FIXED_POINT
  #  define KISS_FFT_COS(phase)  floor(.5+SAMP_MAX * cos (phase))
  #  define KISS_FFT_SIN(phase)  floor(.5+SAMP_MAX * sin (phase))
  #  define HALF_OF(x) ((x)>>1)
  #elif defined(KISS_FFT_USE_SIMD)
  #  define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
  #  define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
  #  define HALF_OF(x) ((x)*_mm_set1_ps(.5))
  #else
  #  define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
  #  define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
  #  define HALF_OF(x) ((x)*((kiss_fft_scalar).5))
  #endif
  
  #define  kf_cexp(x,phase) \
      do{ \
          (x)->r = KISS_FFT_COS(phase);\
          (x)->i = KISS_FFT_SIN(phase);\
      }while(0)
  
  
  /* a debugging function */
  #define pcpx(c)\
      KISS_FFT_DEBUG("%g + %gi\n",(double)((c)->r),(double)((c)->i))
  
  
  #ifdef KISS_FFT_USE_ALLOCA
  // define this to allow use of alloca instead of malloc for temporary buffers
  // Temporary buffers are used in two case:
  // 1. FFT sizes that have "bad" factors. i.e. not 2,3 and 5
  // 2. "in-place" FFTs.  Notice the quotes, since kissfft does not really do an in-place transform.
  #ifdef _MSC_VER
  #include <malloc.h>
  #else
  #include <alloca.h>
  #endif 
  #define  KISS_FFT_TMP_ALLOC(nbytes) alloca(nbytes)
  #define  KISS_FFT_TMP_FREE(ptr)
  #else
  #define  KISS_FFT_TMP_ALLOC(nbytes) KISS_FFT_MALLOC(nbytes)
  #define  KISS_FFT_TMP_FREE(ptr) KISS_FFT_FREE(ptr)
  #endif
  
  #endif /* _kiss_fft_guts_h */
  
  