1144 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			1144 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2003, 2007-14 Matteo Frigo
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This program is free software; you can redistribute it and/or modify
							 | 
						||
| 
								 | 
							
								 * it under the terms of the GNU General Public License as published by
							 | 
						||
| 
								 | 
							
								 * the Free Software Foundation; either version 2 of the License, or
							 | 
						||
| 
								 | 
							
								 * (at your option) any later version.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This program is distributed in the hope that it will be useful,
							 | 
						||
| 
								 | 
							
								 * but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						||
| 
								 | 
							
								 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
							 | 
						||
| 
								 | 
							
								 * GNU General Public License for more details.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * You should have received a copy of the GNU General Public License
							 | 
						||
| 
								 | 
							
								 * along with this program; if not, write to the Free Software
							 | 
						||
| 
								 | 
							
								 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* FFTW internal header file */
							 | 
						||
| 
								 | 
							
								#ifndef __IFFTW_H__
							 | 
						||
| 
								 | 
							
								#define __IFFTW_H__
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "config.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>		/* size_t */
							 | 
						||
| 
								 | 
							
								#include <stdarg.h>		/* va_list */
							 | 
						||
| 
								 | 
							
								#include <stddef.h>             /* ptrdiff_t */
							 | 
						||
| 
								 | 
							
								#include <limits.h>             /* INT_MAX */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if HAVE_SYS_TYPES_H
							 | 
						||
| 
								 | 
							
								# include <sys/types.h>
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if HAVE_STDINT_H
							 | 
						||
| 
								 | 
							
								# include <stdint.h>             /* uintptr_t, maybe */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if HAVE_INTTYPES_H
							 | 
						||
| 
								 | 
							
								# include <inttypes.h>           /* uintptr_t, maybe */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef __cplusplus
							 | 
						||
| 
								 | 
							
								extern "C"
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#endif /* __cplusplus */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Windows annoyances -- since tests/hook.c uses some internal
							 | 
						||
| 
								 | 
							
								   FFTW functions, we need to given them the dllexport attribute
							 | 
						||
| 
								 | 
							
								   under Windows when compiling as a DLL (see api/fftw3.h). */
							 | 
						||
| 
								 | 
							
								#if defined(FFTW_EXTERN)
							 | 
						||
| 
								 | 
							
								#  define IFFTW_EXTERN FFTW_EXTERN
							 | 
						||
| 
								 | 
							
								#elif (defined(FFTW_DLL) || defined(DLL_EXPORT)) \
							 | 
						||
| 
								 | 
							
								 && (defined(_WIN32) || defined(__WIN32__))
							 | 
						||
| 
								 | 
							
								#  define IFFTW_EXTERN extern __declspec(dllexport)
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#  define IFFTW_EXTERN extern
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* determine precision and name-mangling scheme */
							 | 
						||
| 
								 | 
							
								#define CONCAT(prefix, name) prefix ## name
							 | 
						||
| 
								 | 
							
								#if defined(FFTW_SINGLE)
							 | 
						||
| 
								 | 
							
								  typedef float R;
							 | 
						||
| 
								 | 
							
								# define X(name) CONCAT(fftwf_, name)
							 | 
						||
| 
								 | 
							
								#elif defined(FFTW_LDOUBLE)
							 | 
						||
| 
								 | 
							
								  typedef long double R;
							 | 
						||
| 
								 | 
							
								# define X(name) CONCAT(fftwl_, name)
							 | 
						||
| 
								 | 
							
								# define TRIGREAL_IS_LONG_DOUBLE
							 | 
						||
| 
								 | 
							
								#elif defined(FFTW_QUAD)
							 | 
						||
| 
								 | 
							
								  typedef __float128 R;
							 | 
						||
| 
								 | 
							
								# define X(name) CONCAT(fftwq_, name)
							 | 
						||
| 
								 | 
							
								# define TRIGREAL_IS_QUAD
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								  typedef double R;
							 | 
						||
| 
								 | 
							
								# define X(name) CONCAT(fftw_, name)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								  integral type large enough to contain a stride (what ``int'' should
							 | 
						||
| 
								 | 
							
								  have been in the first place.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								typedef ptrdiff_t INT;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* dummy use of unused parameters to silence compiler warnings */
							 | 
						||
| 
								 | 
							
								#define UNUSED(x) (void)x
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define NELEM(array) ((sizeof(array) / sizeof((array)[0])))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define FFT_SIGN (-1)  /* sign convention for forward transforms */
							 | 
						||
| 
								 | 
							
								extern void X(extract_reim)(int sign, R *c, R **r, R **i);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define REGISTER_SOLVER(p, s) X(solver_register)(p, s)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define STRINGIZEx(x) #x
							 | 
						||
| 
								 | 
							
								#define STRINGIZE(x) STRINGIZEx(x)
							 | 
						||
| 
								 | 
							
								#define CIMPLIES(ante, post) (!(ante) || (post))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* define HAVE_SIMD if any simd extensions are supported */
							 | 
						||
| 
								 | 
							
								#if defined(HAVE_SSE) || defined(HAVE_SSE2) || \
							 | 
						||
| 
								 | 
							
								      defined(HAVE_AVX) || defined(HAVE_AVX_128_FMA) || \
							 | 
						||
| 
								 | 
							
								      defined(HAVE_AVX2) || defined(HAVE_AVX512) || \
							 | 
						||
| 
								 | 
							
								      defined(HAVE_KCVI) || \
							 | 
						||
| 
								 | 
							
								      defined(HAVE_ALTIVEC) || defined(HAVE_VSX) || \
							 | 
						||
| 
								 | 
							
								      defined(HAVE_MIPS_PS) || \
							 | 
						||
| 
								 | 
							
								      defined(HAVE_GENERIC_SIMD128) || defined(HAVE_GENERIC_SIMD256)
							 | 
						||
| 
								 | 
							
								#define HAVE_SIMD 1
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#define HAVE_SIMD 0
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								extern int X(have_simd_sse2)(void);
							 | 
						||
| 
								 | 
							
								extern int X(have_simd_avx)(void);
							 | 
						||
| 
								 | 
							
								extern int X(have_simd_avx_128_fma)(void);
							 | 
						||
| 
								 | 
							
								extern int X(have_simd_avx2)(void);
							 | 
						||
| 
								 | 
							
								extern int X(have_simd_avx2_128)(void);
							 | 
						||
| 
								 | 
							
								extern int X(have_simd_avx512)(void);
							 | 
						||
| 
								 | 
							
								extern int X(have_simd_altivec)(void);
							 | 
						||
| 
								 | 
							
								extern int X(have_simd_vsx)(void);
							 | 
						||
| 
								 | 
							
								extern int X(have_simd_neon)(void);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* forward declarations */
							 | 
						||
| 
								 | 
							
								typedef struct problem_s problem;
							 | 
						||
| 
								 | 
							
								typedef struct plan_s plan;
							 | 
						||
| 
								 | 
							
								typedef struct solver_s solver;
							 | 
						||
| 
								 | 
							
								typedef struct planner_s planner;
							 | 
						||
| 
								 | 
							
								typedef struct printer_s printer;
							 | 
						||
| 
								 | 
							
								typedef struct scanner_s scanner;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* alloca: */
							 | 
						||
| 
								 | 
							
								#if HAVE_SIMD
							 | 
						||
| 
								 | 
							
								#  if defined(HAVE_KCVI) || defined(HAVE_AVX512)
							 | 
						||
| 
								 | 
							
								#    define MIN_ALIGNMENT 64
							 | 
						||
| 
								 | 
							
								#  elif defined(HAVE_AVX) || defined(HAVE_AVX2) || defined(HAVE_GENERIC_SIMD256)
							 | 
						||
| 
								 | 
							
								#    define MIN_ALIGNMENT 32  /* best alignment for AVX, conservative for
							 | 
						||
| 
								 | 
							
											       * everything else */
							 | 
						||
| 
								 | 
							
								#  else
							 | 
						||
| 
								 | 
							
								     /* Note that we cannot use 32-byte alignment for all SIMD.  For
							 | 
						||
| 
								 | 
							
									example, MacOS X malloc is 16-byte aligned, but there was no
							 | 
						||
| 
								 | 
							
									posix_memalign in MacOS X until version 10.6. */
							 | 
						||
| 
								 | 
							
								#    define MIN_ALIGNMENT 16
							 | 
						||
| 
								 | 
							
								#  endif
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(HAVE_ALLOCA) && defined(FFTW_ENABLE_ALLOCA)
							 | 
						||
| 
								 | 
							
								   /* use alloca if available */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef alloca
							 | 
						||
| 
								 | 
							
								#ifdef __GNUC__
							 | 
						||
| 
								 | 
							
								# define alloca __builtin_alloca
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								# ifdef _MSC_VER
							 | 
						||
| 
								 | 
							
								#  include <malloc.h>
							 | 
						||
| 
								 | 
							
								#  define alloca _alloca
							 | 
						||
| 
								 | 
							
								# else
							 | 
						||
| 
								 | 
							
								#  if HAVE_ALLOCA_H
							 | 
						||
| 
								 | 
							
								#   include <alloca.h>
							 | 
						||
| 
								 | 
							
								#  else
							 | 
						||
| 
								 | 
							
								#   ifdef _AIX
							 | 
						||
| 
								 | 
							
								 #pragma alloca
							 | 
						||
| 
								 | 
							
								#   else
							 | 
						||
| 
								 | 
							
								#    ifndef alloca /* predefined by HP cc +Olibcalls */
							 | 
						||
| 
								 | 
							
								void *alloca(size_t);
							 | 
						||
| 
								 | 
							
								#    endif
							 | 
						||
| 
								 | 
							
								#   endif
							 | 
						||
| 
								 | 
							
								#  endif
							 | 
						||
| 
								 | 
							
								# endif
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#  ifdef MIN_ALIGNMENT
							 | 
						||
| 
								 | 
							
								#    define STACK_MALLOC(T, p, n)				\
							 | 
						||
| 
								 | 
							
								     {								\
							 | 
						||
| 
								 | 
							
								         p = (T)alloca((n) + MIN_ALIGNMENT);			\
							 | 
						||
| 
								 | 
							
								         p = (T)(((uintptr_t)p + (MIN_ALIGNMENT - 1)) &	\
							 | 
						||
| 
								 | 
							
								               (~(uintptr_t)(MIN_ALIGNMENT - 1)));		\
							 | 
						||
| 
								 | 
							
								     }
							 | 
						||
| 
								 | 
							
								#    define STACK_FREE(n) 
							 | 
						||
| 
								 | 
							
								#  else /* HAVE_ALLOCA && !defined(MIN_ALIGNMENT) */
							 | 
						||
| 
								 | 
							
								#    define STACK_MALLOC(T, p, n) p = (T)alloca(n) 
							 | 
						||
| 
								 | 
							
								#    define STACK_FREE(n) 
							 | 
						||
| 
								 | 
							
								#  endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#else /* ! HAVE_ALLOCA */
							 | 
						||
| 
								 | 
							
								   /* use malloc instead of alloca */
							 | 
						||
| 
								 | 
							
								#  define STACK_MALLOC(T, p, n) p = (T)MALLOC(n, OTHER)
							 | 
						||
| 
								 | 
							
								#  define STACK_FREE(n) X(ifree)(n)
							 | 
						||
| 
								 | 
							
								#endif /* ! HAVE_ALLOCA */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* allocation of buffers.  If these grow too large use malloc(), else
							 | 
						||
| 
								 | 
							
								   use STACK_MALLOC (hopefully reducing to alloca()). */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* 64KiB ought to be enough for anybody */
							 | 
						||
| 
								 | 
							
								#define MAX_STACK_ALLOC ((size_t)64 * 1024)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define BUF_ALLOC(T, p, n)			\
							 | 
						||
| 
								 | 
							
								{						\
							 | 
						||
| 
								 | 
							
								     if (n < MAX_STACK_ALLOC) {			\
							 | 
						||
| 
								 | 
							
									  STACK_MALLOC(T, p, n);		\
							 | 
						||
| 
								 | 
							
								     } else {					\
							 | 
						||
| 
								 | 
							
									  p = (T)MALLOC(n, BUFFERS);		\
							 | 
						||
| 
								 | 
							
								     }						\
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define BUF_FREE(p, n)				\
							 | 
						||
| 
								 | 
							
								{						\
							 | 
						||
| 
								 | 
							
								     if (n < MAX_STACK_ALLOC) {			\
							 | 
						||
| 
								 | 
							
									  STACK_FREE(p);			\
							 | 
						||
| 
								 | 
							
								     } else {					\
							 | 
						||
| 
								 | 
							
									  X(ifree)(p);				\
							 | 
						||
| 
								 | 
							
								     }						\
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* define uintptr_t if it is not already defined */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef HAVE_UINTPTR_T
							 | 
						||
| 
								 | 
							
								#  if SIZEOF_VOID_P == 0
							 | 
						||
| 
								 | 
							
								#    error sizeof void* is unknown!
							 | 
						||
| 
								 | 
							
								#  elif SIZEOF_UNSIGNED_INT == SIZEOF_VOID_P
							 | 
						||
| 
								 | 
							
								     typedef unsigned int uintptr_t;
							 | 
						||
| 
								 | 
							
								#  elif SIZEOF_UNSIGNED_LONG == SIZEOF_VOID_P
							 | 
						||
| 
								 | 
							
								     typedef unsigned long uintptr_t;
							 | 
						||
| 
								 | 
							
								#  elif SIZEOF_UNSIGNED_LONG_LONG == SIZEOF_VOID_P
							 | 
						||
| 
								 | 
							
								     typedef unsigned long long uintptr_t;
							 | 
						||
| 
								 | 
							
								#  else
							 | 
						||
| 
								 | 
							
								#    error no unsigned integer type matches void* sizeof!
							 | 
						||
| 
								 | 
							
								#  endif
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* We can do an optimization for copying pairs of (aligned) floats
							 | 
						||
| 
								 | 
							
								   when in single precision if 2*float = double. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define FFTW_2R_IS_DOUBLE (defined(FFTW_SINGLE) \
							 | 
						||
| 
								 | 
							
								                           && SIZEOF_FLOAT != 0 \
							 | 
						||
| 
								 | 
							
								                           && SIZEOF_DOUBLE == 2*SIZEOF_FLOAT)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define DOUBLE_ALIGNED(p) ((((uintptr_t)(p)) % sizeof(double)) == 0)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* assert.c: */
							 | 
						||
| 
								 | 
							
								IFFTW_EXTERN void X(assertion_failed)(const char *s, 
							 | 
						||
| 
								 | 
							
												      int line, const char *file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* always check */
							 | 
						||
| 
								 | 
							
								#define CK(ex)						 \
							 | 
						||
| 
								 | 
							
								      (void)((ex) || (X(assertion_failed)(#ex, __LINE__, __FILE__), 0))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef FFTW_DEBUG
							 | 
						||
| 
								 | 
							
								/* check only if debug enabled */
							 | 
						||
| 
								 | 
							
								#define A(ex)						 \
							 | 
						||
| 
								 | 
							
								      (void)((ex) || (X(assertion_failed)(#ex, __LINE__, __FILE__), 0))
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#define A(ex) /* nothing */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								extern void X(debug)(const char *format, ...);
							 | 
						||
| 
								 | 
							
								#define D X(debug)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* kalloc.c: */
							 | 
						||
| 
								 | 
							
								extern void *X(kernel_malloc)(size_t n);
							 | 
						||
| 
								 | 
							
								extern void X(kernel_free)(void *p);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* alloc.c: */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* objects allocated by malloc, for statistical purposes */
							 | 
						||
| 
								 | 
							
								enum malloc_tag {
							 | 
						||
| 
								 | 
							
								     EVERYTHING,
							 | 
						||
| 
								 | 
							
								     PLANS,
							 | 
						||
| 
								 | 
							
								     SOLVERS,
							 | 
						||
| 
								 | 
							
								     PROBLEMS,
							 | 
						||
| 
								 | 
							
								     BUFFERS,
							 | 
						||
| 
								 | 
							
								     HASHT,
							 | 
						||
| 
								 | 
							
								     TENSORS,
							 | 
						||
| 
								 | 
							
								     PLANNERS,
							 | 
						||
| 
								 | 
							
								     SLVDESCS,
							 | 
						||
| 
								 | 
							
								     TWIDDLES,
							 | 
						||
| 
								 | 
							
								     STRIDES,
							 | 
						||
| 
								 | 
							
								     OTHER,
							 | 
						||
| 
								 | 
							
								     MALLOC_WHAT_LAST		/* must be last */
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								IFFTW_EXTERN void X(ifree)(void *ptr);
							 | 
						||
| 
								 | 
							
								extern void X(ifree0)(void *ptr);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								IFFTW_EXTERN void *X(malloc_plain)(size_t sz);
							 | 
						||
| 
								 | 
							
								#define MALLOC(n, what)  X(malloc_plain)(n)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* low-resolution clock */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef FAKE_CRUDE_TIME
							 | 
						||
| 
								 | 
							
								 typedef int crude_time;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								# if TIME_WITH_SYS_TIME
							 | 
						||
| 
								 | 
							
								#  include <sys/time.h>
							 | 
						||
| 
								 | 
							
								#  include <time.h>
							 | 
						||
| 
								 | 
							
								# else
							 | 
						||
| 
								 | 
							
								#  if HAVE_SYS_TIME_H
							 | 
						||
| 
								 | 
							
								#   include <sys/time.h>
							 | 
						||
| 
								 | 
							
								#  else
							 | 
						||
| 
								 | 
							
								#   include <time.h>
							 | 
						||
| 
								 | 
							
								#  endif
							 | 
						||
| 
								 | 
							
								# endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# ifdef HAVE_BSDGETTIMEOFDAY
							 | 
						||
| 
								 | 
							
								# ifndef HAVE_GETTIMEOFDAY
							 | 
						||
| 
								 | 
							
								# define gettimeofday BSDgettimeofday
							 | 
						||
| 
								 | 
							
								# define HAVE_GETTIMEOFDAY 1
							 | 
						||
| 
								 | 
							
								# endif
							 | 
						||
| 
								 | 
							
								# endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# if defined(HAVE_GETTIMEOFDAY)
							 | 
						||
| 
								 | 
							
								   typedef struct timeval crude_time;
							 | 
						||
| 
								 | 
							
								# else
							 | 
						||
| 
								 | 
							
								   typedef clock_t crude_time;
							 | 
						||
| 
								 | 
							
								# endif
							 | 
						||
| 
								 | 
							
								#endif /* else FAKE_CRUDE_TIME */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								crude_time X(get_crude_time)(void);
							 | 
						||
| 
								 | 
							
								double X(elapsed_since)(const planner *plnr, const problem *p,
							 | 
						||
| 
								 | 
							
											crude_time t0); /* time in seconds since t0 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* ops.c: */
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * ops counter.  The total number of additions is add + fma
							 | 
						||
| 
								 | 
							
								 * and the total number of multiplications is mul + fma.
							 | 
						||
| 
								 | 
							
								 * Total flops = add + mul + 2 * fma
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								     double add;
							 | 
						||
| 
								 | 
							
								     double mul;
							 | 
						||
| 
								 | 
							
								     double fma;
							 | 
						||
| 
								 | 
							
								     double other;
							 | 
						||
| 
								 | 
							
								} opcnt;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void X(ops_zero)(opcnt *dst);
							 | 
						||
| 
								 | 
							
								void X(ops_other)(INT o, opcnt *dst);
							 | 
						||
| 
								 | 
							
								void X(ops_cpy)(const opcnt *src, opcnt *dst);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void X(ops_add)(const opcnt *a, const opcnt *b, opcnt *dst);
							 | 
						||
| 
								 | 
							
								void X(ops_add2)(const opcnt *a, opcnt *dst);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* dst = m * a + b */
							 | 
						||
| 
								 | 
							
								void X(ops_madd)(INT m, const opcnt *a, const opcnt *b, opcnt *dst);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* dst += m * a */
							 | 
						||
| 
								 | 
							
								void X(ops_madd2)(INT m, const opcnt *a, opcnt *dst);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* minmax.c: */
							 | 
						||
| 
								 | 
							
								INT X(imax)(INT a, INT b);
							 | 
						||
| 
								 | 
							
								INT X(imin)(INT a, INT b);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* iabs.c: */
							 | 
						||
| 
								 | 
							
								INT X(iabs)(INT a);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* inline version */
							 | 
						||
| 
								 | 
							
								#define IABS(x) (((x) < 0) ? (0 - (x)) : (x))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* md5.c */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if SIZEOF_UNSIGNED_INT >= 4
							 | 
						||
| 
								 | 
							
								typedef unsigned int md5uint;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								typedef unsigned long md5uint; /* at least 32 bits as per C standard */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef md5uint md5sig[4];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								     md5sig s; /* state and signature */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     /* fields not meant to be used outside md5.c: */
							 | 
						||
| 
								 | 
							
								     unsigned char c[64]; /* stuff not yet processed */
							 | 
						||
| 
								 | 
							
								     unsigned l;  /* total length.  Should be 64 bits long, but this is
							 | 
						||
| 
								 | 
							
										     good enough for us */
							 | 
						||
| 
								 | 
							
								} md5;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void X(md5begin)(md5 *p);
							 | 
						||
| 
								 | 
							
								void X(md5putb)(md5 *p, const void *d_, size_t len);
							 | 
						||
| 
								 | 
							
								void X(md5puts)(md5 *p, const char *s);
							 | 
						||
| 
								 | 
							
								void X(md5putc)(md5 *p, unsigned char c);
							 | 
						||
| 
								 | 
							
								void X(md5int)(md5 *p, int i);
							 | 
						||
| 
								 | 
							
								void X(md5INT)(md5 *p, INT i);
							 | 
						||
| 
								 | 
							
								void X(md5unsigned)(md5 *p, unsigned i);
							 | 
						||
| 
								 | 
							
								void X(md5end)(md5 *p);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* tensor.c: */
							 | 
						||
| 
								 | 
							
								#define STRUCT_HACK_KR
							 | 
						||
| 
								 | 
							
								#undef STRUCT_HACK_C99
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								     INT n;
							 | 
						||
| 
								 | 
							
								     INT is;			/* input stride */
							 | 
						||
| 
								 | 
							
								     INT os;			/* output stride */
							 | 
						||
| 
								 | 
							
								} iodim;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								     int rnk;
							 | 
						||
| 
								 | 
							
								#if defined(STRUCT_HACK_KR)
							 | 
						||
| 
								 | 
							
								     iodim dims[1];
							 | 
						||
| 
								 | 
							
								#elif defined(STRUCT_HACK_C99)
							 | 
						||
| 
								 | 
							
								     iodim dims[];
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								     iodim *dims;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								} tensor;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								  Definition of rank -infinity.
							 | 
						||
| 
								 | 
							
								  This definition has the property that if you want rank 0 or 1,
							 | 
						||
| 
								 | 
							
								  you can simply test for rank <= 1.  This is a common case.
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								  A tensor of rank -infinity has size 0.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								#define RNK_MINFTY  INT_MAX
							 | 
						||
| 
								 | 
							
								#define FINITE_RNK(rnk) ((rnk) != RNK_MINFTY)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef enum { INPLACE_IS, INPLACE_OS } inplace_kind;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								tensor *X(mktensor)(int rnk);
							 | 
						||
| 
								 | 
							
								tensor *X(mktensor_0d)(void);
							 | 
						||
| 
								 | 
							
								tensor *X(mktensor_1d)(INT n, INT is, INT os);
							 | 
						||
| 
								 | 
							
								tensor *X(mktensor_2d)(INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
										       INT n1, INT is1, INT os1);
							 | 
						||
| 
								 | 
							
								tensor *X(mktensor_3d)(INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
										       INT n1, INT is1, INT os1,
							 | 
						||
| 
								 | 
							
										       INT n2, INT is2, INT os2);
							 | 
						||
| 
								 | 
							
								tensor *X(mktensor_4d)(INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
										       INT n1, INT is1, INT os1,
							 | 
						||
| 
								 | 
							
										       INT n2, INT is2, INT os2,
							 | 
						||
| 
								 | 
							
										       INT n3, INT is3, INT os3);
							 | 
						||
| 
								 | 
							
								tensor *X(mktensor_5d)(INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
										       INT n1, INT is1, INT os1,
							 | 
						||
| 
								 | 
							
										       INT n2, INT is2, INT os2,
							 | 
						||
| 
								 | 
							
										       INT n3, INT is3, INT os3,
							 | 
						||
| 
								 | 
							
										       INT n4, INT is4, INT os4);
							 | 
						||
| 
								 | 
							
								INT X(tensor_sz)(const tensor *sz);
							 | 
						||
| 
								 | 
							
								void X(tensor_md5)(md5 *p, const tensor *t);
							 | 
						||
| 
								 | 
							
								INT X(tensor_max_index)(const tensor *sz);
							 | 
						||
| 
								 | 
							
								INT X(tensor_min_istride)(const tensor *sz);
							 | 
						||
| 
								 | 
							
								INT X(tensor_min_ostride)(const tensor *sz);
							 | 
						||
| 
								 | 
							
								INT X(tensor_min_stride)(const tensor *sz);
							 | 
						||
| 
								 | 
							
								int X(tensor_inplace_strides)(const tensor *sz);
							 | 
						||
| 
								 | 
							
								int X(tensor_inplace_strides2)(const tensor *a, const tensor *b);
							 | 
						||
| 
								 | 
							
								int X(tensor_strides_decrease)(const tensor *sz, const tensor *vecsz,
							 | 
						||
| 
								 | 
							
								                               inplace_kind k);
							 | 
						||
| 
								 | 
							
								tensor *X(tensor_copy)(const tensor *sz);
							 | 
						||
| 
								 | 
							
								int X(tensor_kosherp)(const tensor *x);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								tensor *X(tensor_copy_inplace)(const tensor *sz, inplace_kind k);
							 | 
						||
| 
								 | 
							
								tensor *X(tensor_copy_except)(const tensor *sz, int except_dim);
							 | 
						||
| 
								 | 
							
								tensor *X(tensor_copy_sub)(const tensor *sz, int start_dim, int rnk);
							 | 
						||
| 
								 | 
							
								tensor *X(tensor_compress)(const tensor *sz);
							 | 
						||
| 
								 | 
							
								tensor *X(tensor_compress_contiguous)(const tensor *sz);
							 | 
						||
| 
								 | 
							
								tensor *X(tensor_append)(const tensor *a, const tensor *b);
							 | 
						||
| 
								 | 
							
								void X(tensor_split)(const tensor *sz, tensor **a, int a_rnk, tensor **b);
							 | 
						||
| 
								 | 
							
								int X(tensor_tornk1)(const tensor *t, INT *n, INT *is, INT *os);
							 | 
						||
| 
								 | 
							
								void X(tensor_destroy)(tensor *sz);
							 | 
						||
| 
								 | 
							
								void X(tensor_destroy2)(tensor *a, tensor *b);
							 | 
						||
| 
								 | 
							
								void X(tensor_destroy4)(tensor *a, tensor *b, tensor *c, tensor *d);
							 | 
						||
| 
								 | 
							
								void X(tensor_print)(const tensor *sz, printer *p);
							 | 
						||
| 
								 | 
							
								int X(dimcmp)(const iodim *a, const iodim *b);
							 | 
						||
| 
								 | 
							
								int X(tensor_equal)(const tensor *a, const tensor *b);
							 | 
						||
| 
								 | 
							
								int X(tensor_inplace_locations)(const tensor *sz, const tensor *vecsz);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* problem.c: */
							 | 
						||
| 
								 | 
							
								enum { 
							 | 
						||
| 
								 | 
							
								     /* a problem that cannot be solved */
							 | 
						||
| 
								 | 
							
								     PROBLEM_UNSOLVABLE,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     PROBLEM_DFT, 
							 | 
						||
| 
								 | 
							
								     PROBLEM_RDFT,
							 | 
						||
| 
								 | 
							
								     PROBLEM_RDFT2,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     /* for mpi/ subdirectory */
							 | 
						||
| 
								 | 
							
								     PROBLEM_MPI_DFT,
							 | 
						||
| 
								 | 
							
								     PROBLEM_MPI_RDFT,
							 | 
						||
| 
								 | 
							
								     PROBLEM_MPI_RDFT2,
							 | 
						||
| 
								 | 
							
								     PROBLEM_MPI_TRANSPOSE,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     PROBLEM_LAST 
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								     int problem_kind;
							 | 
						||
| 
								 | 
							
								     void (*hash) (const problem *ego, md5 *p);
							 | 
						||
| 
								 | 
							
								     void (*zero) (const problem *ego);
							 | 
						||
| 
								 | 
							
								     void (*print) (const problem *ego, printer *p);
							 | 
						||
| 
								 | 
							
								     void (*destroy) (problem *ego);
							 | 
						||
| 
								 | 
							
								} problem_adt;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct problem_s {
							 | 
						||
| 
								 | 
							
								     const problem_adt *adt;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								problem *X(mkproblem)(size_t sz, const problem_adt *adt);
							 | 
						||
| 
								 | 
							
								void X(problem_destroy)(problem *ego);
							 | 
						||
| 
								 | 
							
								problem *X(mkproblem_unsolvable)(void);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* print.c */
							 | 
						||
| 
								 | 
							
								struct printer_s {
							 | 
						||
| 
								 | 
							
								     void (*print)(printer *p, const char *format, ...);
							 | 
						||
| 
								 | 
							
								     void (*vprint)(printer *p, const char *format, va_list ap);
							 | 
						||
| 
								 | 
							
								     void (*putchr)(printer *p, char c);
							 | 
						||
| 
								 | 
							
								     void (*cleanup)(printer *p);
							 | 
						||
| 
								 | 
							
								     int indent;
							 | 
						||
| 
								 | 
							
								     int indent_incr;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								printer *X(mkprinter)(size_t size, 
							 | 
						||
| 
								 | 
							
										      void (*putchr)(printer *p, char c),
							 | 
						||
| 
								 | 
							
										      void (*cleanup)(printer *p));
							 | 
						||
| 
								 | 
							
								IFFTW_EXTERN void X(printer_destroy)(printer *p);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* scan.c */
							 | 
						||
| 
								 | 
							
								struct scanner_s {
							 | 
						||
| 
								 | 
							
								     int (*scan)(scanner *sc, const char *format, ...);
							 | 
						||
| 
								 | 
							
								     int (*vscan)(scanner *sc, const char *format, va_list ap);
							 | 
						||
| 
								 | 
							
								     int (*getchr)(scanner *sc);
							 | 
						||
| 
								 | 
							
								     int ungotc;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								scanner *X(mkscanner)(size_t size, int (*getchr)(scanner *sc));
							 | 
						||
| 
								 | 
							
								void X(scanner_destroy)(scanner *sc);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* plan.c: */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								enum wakefulness {
							 | 
						||
| 
								 | 
							
								     SLEEPY,
							 | 
						||
| 
								 | 
							
								     AWAKE_ZERO,
							 | 
						||
| 
								 | 
							
								     AWAKE_SQRTN_TABLE,
							 | 
						||
| 
								 | 
							
								     AWAKE_SINCOS
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								     void (*solve)(const plan *ego, const problem *p);
							 | 
						||
| 
								 | 
							
								     void (*awake)(plan *ego, enum wakefulness wakefulness);
							 | 
						||
| 
								 | 
							
								     void (*print)(const plan *ego, printer *p);
							 | 
						||
| 
								 | 
							
								     void (*destroy)(plan *ego);
							 | 
						||
| 
								 | 
							
								} plan_adt;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct plan_s {
							 | 
						||
| 
								 | 
							
								     const plan_adt *adt;
							 | 
						||
| 
								 | 
							
								     opcnt ops;
							 | 
						||
| 
								 | 
							
								     double pcost;
							 | 
						||
| 
								 | 
							
								     enum wakefulness wakefulness; /* used for debugging only */
							 | 
						||
| 
								 | 
							
								     int could_prune_now_p;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								plan *X(mkplan)(size_t size, const plan_adt *adt);
							 | 
						||
| 
								 | 
							
								void X(plan_destroy_internal)(plan *ego);
							 | 
						||
| 
								 | 
							
								IFFTW_EXTERN void X(plan_awake)(plan *ego, enum wakefulness wakefulness);
							 | 
						||
| 
								 | 
							
								void X(plan_null_destroy)(plan *ego);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* solver.c: */
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								     int problem_kind;
							 | 
						||
| 
								 | 
							
								     plan *(*mkplan)(const solver *ego, const problem *p, planner *plnr);
							 | 
						||
| 
								 | 
							
								     void (*destroy)(solver *ego);
							 | 
						||
| 
								 | 
							
								} solver_adt;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct solver_s {
							 | 
						||
| 
								 | 
							
								     const solver_adt *adt;
							 | 
						||
| 
								 | 
							
								     int refcnt;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								solver *X(mksolver)(size_t size, const solver_adt *adt);
							 | 
						||
| 
								 | 
							
								void X(solver_use)(solver *ego);
							 | 
						||
| 
								 | 
							
								void X(solver_destroy)(solver *ego);
							 | 
						||
| 
								 | 
							
								void X(solver_register)(planner *plnr, solver *s);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* shorthand */
							 | 
						||
| 
								 | 
							
								#define MKSOLVER(type, adt) (type *)X(mksolver)(sizeof(type), adt)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* planner.c */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct slvdesc_s {
							 | 
						||
| 
								 | 
							
								     solver *slv;
							 | 
						||
| 
								 | 
							
								     const char *reg_nam;
							 | 
						||
| 
								 | 
							
								     unsigned nam_hash;
							 | 
						||
| 
								 | 
							
								     int reg_id;
							 | 
						||
| 
								 | 
							
								     int next_for_same_problem_kind;
							 | 
						||
| 
								 | 
							
								} slvdesc;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct solution_s solution; /* opaque */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* interpretation of L and U: 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   - if it returns a plan, the planner guarantees that all applicable
							 | 
						||
| 
								 | 
							
								     plans at least as impatient as U have been tried, and that each
							 | 
						||
| 
								 | 
							
								     plan in the solution is at least as impatient as L.
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								   - if it returns 0, the planner guarantees to have tried all solvers
							 | 
						||
| 
								 | 
							
								     at least as impatient as L, and that none of them was applicable.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   The structure is packed to fit into 64 bits.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								     unsigned l:20;
							 | 
						||
| 
								 | 
							
								     unsigned hash_info:3;
							 | 
						||
| 
								 | 
							
								#    define BITS_FOR_TIMELIMIT 9
							 | 
						||
| 
								 | 
							
								     unsigned timelimit_impatience:BITS_FOR_TIMELIMIT;
							 | 
						||
| 
								 | 
							
								     unsigned u:20;
							 | 
						||
| 
								 | 
							
								     
							 | 
						||
| 
								 | 
							
								     /* abstraction break: we store the solver here to pad the
							 | 
						||
| 
								 | 
							
									structure to 64 bits.  Otherwise, the struct is padded to 64
							 | 
						||
| 
								 | 
							
									bits anyway, and another word is allocated for slvndx. */
							 | 
						||
| 
								 | 
							
								#    define BITS_FOR_SLVNDX 12
							 | 
						||
| 
								 | 
							
								     unsigned slvndx:BITS_FOR_SLVNDX;
							 | 
						||
| 
								 | 
							
								} flags_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* impatience flags  */
							 | 
						||
| 
								 | 
							
								enum {
							 | 
						||
| 
								 | 
							
								     BELIEVE_PCOST = 0x0001,
							 | 
						||
| 
								 | 
							
								     ESTIMATE = 0x0002,
							 | 
						||
| 
								 | 
							
								     NO_DFT_R2HC = 0x0004,
							 | 
						||
| 
								 | 
							
								     NO_SLOW = 0x0008,
							 | 
						||
| 
								 | 
							
								     NO_VRECURSE = 0x0010,
							 | 
						||
| 
								 | 
							
								     NO_INDIRECT_OP = 0x0020,
							 | 
						||
| 
								 | 
							
								     NO_LARGE_GENERIC = 0x0040,
							 | 
						||
| 
								 | 
							
								     NO_RANK_SPLITS = 0x0080,
							 | 
						||
| 
								 | 
							
								     NO_VRANK_SPLITS = 0x0100,
							 | 
						||
| 
								 | 
							
								     NO_NONTHREADED = 0x0200,
							 | 
						||
| 
								 | 
							
								     NO_BUFFERING = 0x0400,
							 | 
						||
| 
								 | 
							
								     NO_FIXED_RADIX_LARGE_N = 0x0800,
							 | 
						||
| 
								 | 
							
								     NO_DESTROY_INPUT = 0x1000,
							 | 
						||
| 
								 | 
							
								     NO_SIMD = 0x2000,
							 | 
						||
| 
								 | 
							
								     CONSERVE_MEMORY = 0x4000,
							 | 
						||
| 
								 | 
							
								     NO_DHT_R2HC = 0x8000,
							 | 
						||
| 
								 | 
							
								     NO_UGLY = 0x10000,
							 | 
						||
| 
								 | 
							
								     ALLOW_PRUNING = 0x20000
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* hashtable information */
							 | 
						||
| 
								 | 
							
								enum {
							 | 
						||
| 
								 | 
							
								     BLESSING = 0x1u,   /* save this entry */
							 | 
						||
| 
								 | 
							
								     H_VALID = 0x2u,    /* valid hastable entry */
							 | 
						||
| 
								 | 
							
								     H_LIVE = 0x4u      /* entry is nonempty, implies H_VALID */
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define PLNR_L(plnr) ((plnr)->flags.l)
							 | 
						||
| 
								 | 
							
								#define PLNR_U(plnr) ((plnr)->flags.u)
							 | 
						||
| 
								 | 
							
								#define PLNR_TIMELIMIT_IMPATIENCE(plnr) ((plnr)->flags.timelimit_impatience)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define ESTIMATEP(plnr) (PLNR_U(plnr) & ESTIMATE)
							 | 
						||
| 
								 | 
							
								#define BELIEVE_PCOSTP(plnr) (PLNR_U(plnr) & BELIEVE_PCOST)
							 | 
						||
| 
								 | 
							
								#define ALLOW_PRUNINGP(plnr) (PLNR_U(plnr) & ALLOW_PRUNING)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define NO_INDIRECT_OP_P(plnr) (PLNR_L(plnr) & NO_INDIRECT_OP)
							 | 
						||
| 
								 | 
							
								#define NO_LARGE_GENERICP(plnr) (PLNR_L(plnr) & NO_LARGE_GENERIC)
							 | 
						||
| 
								 | 
							
								#define NO_RANK_SPLITSP(plnr) (PLNR_L(plnr) & NO_RANK_SPLITS)
							 | 
						||
| 
								 | 
							
								#define NO_VRANK_SPLITSP(plnr) (PLNR_L(plnr) & NO_VRANK_SPLITS)
							 | 
						||
| 
								 | 
							
								#define NO_VRECURSEP(plnr) (PLNR_L(plnr) & NO_VRECURSE)
							 | 
						||
| 
								 | 
							
								#define NO_DFT_R2HCP(plnr) (PLNR_L(plnr) & NO_DFT_R2HC)
							 | 
						||
| 
								 | 
							
								#define NO_SLOWP(plnr) (PLNR_L(plnr) & NO_SLOW)
							 | 
						||
| 
								 | 
							
								#define NO_UGLYP(plnr) (PLNR_L(plnr) & NO_UGLY)
							 | 
						||
| 
								 | 
							
								#define NO_FIXED_RADIX_LARGE_NP(plnr) \
							 | 
						||
| 
								 | 
							
								  (PLNR_L(plnr) & NO_FIXED_RADIX_LARGE_N)
							 | 
						||
| 
								 | 
							
								#define NO_NONTHREADEDP(plnr) \
							 | 
						||
| 
								 | 
							
								  ((PLNR_L(plnr) & NO_NONTHREADED) && (plnr)->nthr > 1)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define NO_DESTROY_INPUTP(plnr) (PLNR_L(plnr) & NO_DESTROY_INPUT)
							 | 
						||
| 
								 | 
							
								#define NO_SIMDP(plnr) (PLNR_L(plnr) & NO_SIMD)
							 | 
						||
| 
								 | 
							
								#define CONSERVE_MEMORYP(plnr) (PLNR_L(plnr) & CONSERVE_MEMORY)
							 | 
						||
| 
								 | 
							
								#define NO_DHT_R2HCP(plnr) (PLNR_L(plnr) & NO_DHT_R2HC)
							 | 
						||
| 
								 | 
							
								#define NO_BUFFERINGP(plnr) (PLNR_L(plnr) & NO_BUFFERING)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef enum { FORGET_ACCURSED, FORGET_EVERYTHING } amnesia;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef enum { 
							 | 
						||
| 
								 | 
							
								     /* WISDOM_NORMAL: planner may or may not use wisdom */
							 | 
						||
| 
								 | 
							
								     WISDOM_NORMAL, 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     /* WISDOM_ONLY: planner must use wisdom and must avoid searching */
							 | 
						||
| 
								 | 
							
								     WISDOM_ONLY, 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     /* WISDOM_IS_BOGUS: planner must return 0 as quickly as possible */
							 | 
						||
| 
								 | 
							
								     WISDOM_IS_BOGUS,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     /* WISDOM_IGNORE_INFEASIBLE: planner ignores infeasible wisdom */
							 | 
						||
| 
								 | 
							
								     WISDOM_IGNORE_INFEASIBLE,
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     /* WISDOM_IGNORE_ALL: planner ignores all */
							 | 
						||
| 
								 | 
							
								     WISDOM_IGNORE_ALL
							 | 
						||
| 
								 | 
							
								} wisdom_state_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								     void (*register_solver)(planner *ego, solver *s);
							 | 
						||
| 
								 | 
							
								     plan *(*mkplan)(planner *ego, const problem *p);
							 | 
						||
| 
								 | 
							
								     void (*forget)(planner *ego, amnesia a);
							 | 
						||
| 
								 | 
							
								     void (*exprt)(planner *ego, printer *p); /* ``export'' is a reserved
							 | 
						||
| 
								 | 
							
														 word in C++. */
							 | 
						||
| 
								 | 
							
								     int (*imprt)(planner *ego, scanner *sc);
							 | 
						||
| 
								 | 
							
								} planner_adt;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* hash table of solutions */
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								     solution *solutions;
							 | 
						||
| 
								 | 
							
								     unsigned hashsiz, nelem;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     /* statistics */
							 | 
						||
| 
								 | 
							
								     int lookup, succ_lookup, lookup_iter;
							 | 
						||
| 
								 | 
							
								     int insert, insert_iter, insert_unknown;
							 | 
						||
| 
								 | 
							
								     int nrehash;
							 | 
						||
| 
								 | 
							
								} hashtab;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef enum { COST_SUM, COST_MAX } cost_kind;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct planner_s {
							 | 
						||
| 
								 | 
							
								     const planner_adt *adt;
							 | 
						||
| 
								 | 
							
								     void (*hook)(struct planner_s *plnr, plan *pln, 
							 | 
						||
| 
								 | 
							
										  const problem *p, int optimalp);
							 | 
						||
| 
								 | 
							
								     double (*cost_hook)(const problem *p, double t, cost_kind k);
							 | 
						||
| 
								 | 
							
								     int (*wisdom_ok_hook)(const problem *p, flags_t flags);
							 | 
						||
| 
								 | 
							
								     void (*nowisdom_hook)(const problem *p);
							 | 
						||
| 
								 | 
							
								     wisdom_state_t (*bogosity_hook)(wisdom_state_t state, const problem *p);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     /* solver descriptors */
							 | 
						||
| 
								 | 
							
								     slvdesc *slvdescs;
							 | 
						||
| 
								 | 
							
								     unsigned nslvdesc, slvdescsiz;
							 | 
						||
| 
								 | 
							
								     const char *cur_reg_nam;
							 | 
						||
| 
								 | 
							
								     int cur_reg_id;
							 | 
						||
| 
								 | 
							
								     int slvdescs_for_problem_kind[PROBLEM_LAST];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     wisdom_state_t wisdom_state;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     hashtab htab_blessed;
							 | 
						||
| 
								 | 
							
								     hashtab htab_unblessed;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     int nthr;
							 | 
						||
| 
								 | 
							
								     flags_t flags;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     crude_time start_time;
							 | 
						||
| 
								 | 
							
								     double timelimit; /* elapsed_since(start_time) at which to bail out */
							 | 
						||
| 
								 | 
							
								     int timed_out; /* whether most recent search timed out */
							 | 
						||
| 
								 | 
							
								     int need_timeout_check;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     /* various statistics */
							 | 
						||
| 
								 | 
							
								     int nplan;    /* number of plans evaluated */
							 | 
						||
| 
								 | 
							
								     double pcost, epcost; /* total pcost of measured/estimated plans */
							 | 
						||
| 
								 | 
							
								     int nprob;    /* number of problems evaluated */
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								planner *X(mkplanner)(void);
							 | 
						||
| 
								 | 
							
								void X(planner_destroy)(planner *ego);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								  Iterate over all solvers.   Read:
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								  @article{ baker93iterators,
							 | 
						||
| 
								 | 
							
								  author = "Henry G. Baker, Jr.",
							 | 
						||
| 
								 | 
							
								  title = "Iterators: Signs of Weakness in Object-Oriented Languages",
							 | 
						||
| 
								 | 
							
								  journal = "{ACM} {OOPS} Messenger",
							 | 
						||
| 
								 | 
							
								  volume = "4",
							 | 
						||
| 
								 | 
							
								  number = "3",
							 | 
						||
| 
								 | 
							
								  pages = "18--25"
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								#define FORALL_SOLVERS(ego, s, p, what)			\
							 | 
						||
| 
								 | 
							
								{							\
							 | 
						||
| 
								 | 
							
								     unsigned _cnt;					\
							 | 
						||
| 
								 | 
							
								     for (_cnt = 0; _cnt < ego->nslvdesc; ++_cnt) {	\
							 | 
						||
| 
								 | 
							
									  slvdesc *p = ego->slvdescs + _cnt;		\
							 | 
						||
| 
								 | 
							
									  solver *s = p->slv;				\
							 | 
						||
| 
								 | 
							
									  what;						\
							 | 
						||
| 
								 | 
							
								     }							\
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define FORALL_SOLVERS_OF_KIND(kind, ego, s, p, what)		\
							 | 
						||
| 
								 | 
							
								{								\
							 | 
						||
| 
								 | 
							
								     int _cnt = ego->slvdescs_for_problem_kind[kind]; 		\
							 | 
						||
| 
								 | 
							
								     while (_cnt >= 0) {					\
							 | 
						||
| 
								 | 
							
									  slvdesc *p = ego->slvdescs + _cnt;			\
							 | 
						||
| 
								 | 
							
									  solver *s = p->slv;					\
							 | 
						||
| 
								 | 
							
									  what;							\
							 | 
						||
| 
								 | 
							
									  _cnt = p->next_for_same_problem_kind;			\
							 | 
						||
| 
								 | 
							
								     }								\
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* make plan, destroy problem */
							 | 
						||
| 
								 | 
							
								plan *X(mkplan_d)(planner *ego, problem *p);
							 | 
						||
| 
								 | 
							
								plan *X(mkplan_f_d)(planner *ego, problem *p, 
							 | 
						||
| 
								 | 
							
										    unsigned l_set, unsigned u_set, unsigned u_reset);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* stride.c: */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* If PRECOMPUTE_ARRAY_INDICES is defined, precompute all strides. */
							 | 
						||
| 
								 | 
							
								#if (defined(__i386__) || defined(__x86_64__) || _M_IX86 >= 500) && !defined(FFTW_LDOUBLE)
							 | 
						||
| 
								 | 
							
								#define PRECOMPUTE_ARRAY_INDICES
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								extern const INT X(an_INT_guaranteed_to_be_zero);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef PRECOMPUTE_ARRAY_INDICES
							 | 
						||
| 
								 | 
							
								typedef INT *stride;
							 | 
						||
| 
								 | 
							
								#define WS(stride, i)  (stride[i])
							 | 
						||
| 
								 | 
							
								extern stride X(mkstride)(INT n, INT s);
							 | 
						||
| 
								 | 
							
								void X(stride_destroy)(stride p);
							 | 
						||
| 
								 | 
							
								/* hackery to prevent the compiler from copying the strides array
							 | 
						||
| 
								 | 
							
								   onto the stack */
							 | 
						||
| 
								 | 
							
								#define MAKE_VOLATILE_STRIDE(nptr, x) (x) = (x) + X(an_INT_guaranteed_to_be_zero)
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef INT stride;
							 | 
						||
| 
								 | 
							
								#define WS(stride, i)  (stride * i)
							 | 
						||
| 
								 | 
							
								#define fftwf_mkstride(n, stride) stride
							 | 
						||
| 
								 | 
							
								#define fftw_mkstride(n, stride) stride
							 | 
						||
| 
								 | 
							
								#define fftwl_mkstride(n, stride) stride
							 | 
						||
| 
								 | 
							
								#define fftwf_stride_destroy(p) ((void) p)
							 | 
						||
| 
								 | 
							
								#define fftw_stride_destroy(p) ((void) p)
							 | 
						||
| 
								 | 
							
								#define fftwl_stride_destroy(p) ((void) p)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* hackery to prevent the compiler from ``optimizing'' induction
							 | 
						||
| 
								 | 
							
								   variables in codelet loops.  The problem is that for each K and for
							 | 
						||
| 
								 | 
							
								   each expression of the form P[I + STRIDE * K] in a loop, most
							 | 
						||
| 
								 | 
							
								   compilers will try to lift an induction variable PK := &P[I + STRIDE * K].
							 | 
						||
| 
								 | 
							
								   For large values of K this behavior overflows the
							 | 
						||
| 
								 | 
							
								   register set, which is likely worse than doing the index computation
							 | 
						||
| 
								 | 
							
								   in the first place.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   If we guess that there are more than
							 | 
						||
| 
								 | 
							
								   ESTIMATED_AVAILABLE_INDEX_REGISTERS such pointers, we deliberately confuse
							 | 
						||
| 
								 | 
							
								   the compiler by setting STRIDE ^= ZERO, where ZERO is a value guaranteed to
							 | 
						||
| 
								 | 
							
								   be 0, but the compiler does not know this. 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   16 registers ought to be enough for anybody, or so the amd64 and ARM ISA's
							 | 
						||
| 
								 | 
							
								   seem to imply.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								#define ESTIMATED_AVAILABLE_INDEX_REGISTERS 16
							 | 
						||
| 
								 | 
							
								#define MAKE_VOLATILE_STRIDE(nptr, x)                   \
							 | 
						||
| 
								 | 
							
								     (nptr <= ESTIMATED_AVAILABLE_INDEX_REGISTERS ?     \
							 | 
						||
| 
								 | 
							
								        0 :                                             \
							 | 
						||
| 
								 | 
							
								      ((x) = (x) ^ X(an_INT_guaranteed_to_be_zero)))
							 | 
						||
| 
								 | 
							
								#endif /* PRECOMPUTE_ARRAY_INDICES */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* solvtab.c */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct solvtab_s { void (*reg)(planner *); const char *reg_nam; };
							 | 
						||
| 
								 | 
							
								typedef struct solvtab_s solvtab[];
							 | 
						||
| 
								 | 
							
								void X(solvtab_exec)(const solvtab tbl, planner *p);
							 | 
						||
| 
								 | 
							
								#define SOLVTAB(s) { s, STRINGIZE(s) }
							 | 
						||
| 
								 | 
							
								#define SOLVTAB_END { 0, 0 }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* pickdim.c */
							 | 
						||
| 
								 | 
							
								int X(pickdim)(int which_dim, const int *buddies, size_t nbuddies,
							 | 
						||
| 
								 | 
							
									       const tensor *sz, int oop, int *dp);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* twiddle.c */
							 | 
						||
| 
								 | 
							
								/* little language to express twiddle factors computation */
							 | 
						||
| 
								 | 
							
								enum { TW_COS = 0, TW_SIN = 1, TW_CEXP = 2, TW_NEXT = 3, 
							 | 
						||
| 
								 | 
							
								       TW_FULL = 4, TW_HALF = 5 };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct {
							 | 
						||
| 
								 | 
							
								     unsigned char op;
							 | 
						||
| 
								 | 
							
								     signed char v;
							 | 
						||
| 
								 | 
							
								     short i;
							 | 
						||
| 
								 | 
							
								} tw_instr;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct twid_s {
							 | 
						||
| 
								 | 
							
								     R *W;                     /* array of twiddle factors */
							 | 
						||
| 
								 | 
							
								     INT n, r, m;                /* transform order, radix, # twiddle rows */
							 | 
						||
| 
								 | 
							
								     int refcnt;
							 | 
						||
| 
								 | 
							
								     const tw_instr *instr;
							 | 
						||
| 
								 | 
							
								     struct twid_s *cdr;
							 | 
						||
| 
								 | 
							
								     enum wakefulness wakefulness;
							 | 
						||
| 
								 | 
							
								} twid;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								INT X(twiddle_length)(INT r, const tw_instr *p);
							 | 
						||
| 
								 | 
							
								void X(twiddle_awake)(enum wakefulness wakefulness,
							 | 
						||
| 
								 | 
							
										      twid **pp, const tw_instr *instr, INT n, INT r, INT m);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* trig.c */
							 | 
						||
| 
								 | 
							
								#if defined(TRIGREAL_IS_LONG_DOUBLE)
							 | 
						||
| 
								 | 
							
								   typedef long double trigreal;
							 | 
						||
| 
								 | 
							
								#elif defined(TRIGREAL_IS_QUAD)
							 | 
						||
| 
								 | 
							
								   typedef __float128 trigreal;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								   typedef double trigreal;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef struct triggen_s triggen;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								struct triggen_s {
							 | 
						||
| 
								 | 
							
								     void (*cexp)(triggen *t, INT m, R *result);
							 | 
						||
| 
								 | 
							
								     void (*cexpl)(triggen *t, INT m, trigreal *result);
							 | 
						||
| 
								 | 
							
								     void (*rotate)(triggen *p, INT m, R xr, R xi, R *res);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     INT twshft;
							 | 
						||
| 
								 | 
							
								     INT twradix;
							 | 
						||
| 
								 | 
							
								     INT twmsk;
							 | 
						||
| 
								 | 
							
								     trigreal *W0, *W1;
							 | 
						||
| 
								 | 
							
								     INT n;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								triggen *X(mktriggen)(enum wakefulness wakefulness, INT n);
							 | 
						||
| 
								 | 
							
								void X(triggen_destroy)(triggen *p);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* primes.c: */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define MULMOD(x, y, p) \
							 | 
						||
| 
								 | 
							
								   (((x) <= 92681 - (y)) ? ((x) * (y)) % (p) : X(safe_mulmod)(x, y, p))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								INT X(safe_mulmod)(INT x, INT y, INT p);
							 | 
						||
| 
								 | 
							
								INT X(power_mod)(INT n, INT m, INT p);
							 | 
						||
| 
								 | 
							
								INT X(find_generator)(INT p);
							 | 
						||
| 
								 | 
							
								INT X(first_divisor)(INT n);
							 | 
						||
| 
								 | 
							
								int X(is_prime)(INT n);
							 | 
						||
| 
								 | 
							
								INT X(next_prime)(INT n);
							 | 
						||
| 
								 | 
							
								int X(factors_into)(INT n, const INT *primes);
							 | 
						||
| 
								 | 
							
								int X(factors_into_small_primes)(INT n);
							 | 
						||
| 
								 | 
							
								INT X(choose_radix)(INT r, INT n);
							 | 
						||
| 
								 | 
							
								INT X(isqrt)(INT n);
							 | 
						||
| 
								 | 
							
								INT X(modulo)(INT a, INT n);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define GENERIC_MIN_BAD 173 /* min prime for which generic becomes bad */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* thresholds below which certain solvers are considered SLOW.  These are guesses
							 | 
						||
| 
								 | 
							
								   believed to be conservative */
							 | 
						||
| 
								 | 
							
								#define GENERIC_MAX_SLOW     16
							 | 
						||
| 
								 | 
							
								#define RADER_MAX_SLOW       32
							 | 
						||
| 
								 | 
							
								#define BLUESTEIN_MAX_SLOW   24
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* rader.c: */
							 | 
						||
| 
								 | 
							
								typedef struct rader_tls rader_tl;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void X(rader_tl_insert)(INT k1, INT k2, INT k3, R *W, rader_tl **tl);
							 | 
						||
| 
								 | 
							
								R *X(rader_tl_find)(INT k1, INT k2, INT k3, rader_tl *t);
							 | 
						||
| 
								 | 
							
								void X(rader_tl_delete)(R *W, rader_tl **tl);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* copy/transposition routines */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* lower bound to the cache size, for tiled routines */
							 | 
						||
| 
								 | 
							
								#define CACHESIZE 8192
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								INT X(compute_tilesz)(INT vl, int how_many_tiles_in_cache);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void X(tile2d)(INT n0l, INT n0u, INT n1l, INT n1u, INT tilesz,
							 | 
						||
| 
								 | 
							
									       void (*f)(INT n0l, INT n0u, INT n1l, INT n1u, void *args),
							 | 
						||
| 
								 | 
							
									       void *args);
							 | 
						||
| 
								 | 
							
								void X(cpy1d)(R *I, R *O, INT n0, INT is0, INT os0, INT vl);
							 | 
						||
| 
								 | 
							
								void X(zero1d_pair)(R *O0, R *O1, INT n0, INT os0);
							 | 
						||
| 
								 | 
							
								void X(cpy2d)(R *I, R *O,
							 | 
						||
| 
								 | 
							
									      INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
									      INT n1, INT is1, INT os1,
							 | 
						||
| 
								 | 
							
									      INT vl);
							 | 
						||
| 
								 | 
							
								void X(cpy2d_ci)(R *I, R *O,
							 | 
						||
| 
								 | 
							
										 INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
										 INT n1, INT is1, INT os1,
							 | 
						||
| 
								 | 
							
										 INT vl);
							 | 
						||
| 
								 | 
							
								void X(cpy2d_co)(R *I, R *O,
							 | 
						||
| 
								 | 
							
										 INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
										 INT n1, INT is1, INT os1,
							 | 
						||
| 
								 | 
							
										 INT vl);
							 | 
						||
| 
								 | 
							
								void X(cpy2d_tiled)(R *I, R *O,
							 | 
						||
| 
								 | 
							
										    INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
										    INT n1, INT is1, INT os1, 
							 | 
						||
| 
								 | 
							
										    INT vl);
							 | 
						||
| 
								 | 
							
								void X(cpy2d_tiledbuf)(R *I, R *O,
							 | 
						||
| 
								 | 
							
										       INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
										       INT n1, INT is1, INT os1, 
							 | 
						||
| 
								 | 
							
										       INT vl);
							 | 
						||
| 
								 | 
							
								void X(cpy2d_pair)(R *I0, R *I1, R *O0, R *O1,
							 | 
						||
| 
								 | 
							
										   INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
										   INT n1, INT is1, INT os1);
							 | 
						||
| 
								 | 
							
								void X(cpy2d_pair_ci)(R *I0, R *I1, R *O0, R *O1,
							 | 
						||
| 
								 | 
							
										      INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
										      INT n1, INT is1, INT os1);
							 | 
						||
| 
								 | 
							
								void X(cpy2d_pair_co)(R *I0, R *I1, R *O0, R *O1,
							 | 
						||
| 
								 | 
							
										      INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
										      INT n1, INT is1, INT os1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void X(transpose)(R *I, INT n, INT s0, INT s1, INT vl);
							 | 
						||
| 
								 | 
							
								void X(transpose_tiled)(R *I, INT n, INT s0, INT s1, INT vl);
							 | 
						||
| 
								 | 
							
								void X(transpose_tiledbuf)(R *I, INT n, INT s0, INT s1, INT vl);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef void (*transpose_func)(R *I, INT n, INT s0, INT s1, INT vl);
							 | 
						||
| 
								 | 
							
								typedef void (*cpy2d_func)(R *I, R *O,
							 | 
						||
| 
								 | 
							
											   INT n0, INT is0, INT os0,
							 | 
						||
| 
								 | 
							
											   INT n1, INT is1, INT os1,
							 | 
						||
| 
								 | 
							
											   INT vl);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* misc stuff */
							 | 
						||
| 
								 | 
							
								void X(null_awake)(plan *ego, enum wakefulness wakefulness);
							 | 
						||
| 
								 | 
							
								double X(iestimate_cost)(const planner *, const plan *, const problem *);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef FFTW_RANDOM_ESTIMATOR
							 | 
						||
| 
								 | 
							
								extern unsigned X(random_estimate_seed);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								double X(measure_execution_time)(const planner *plnr, 
							 | 
						||
| 
								 | 
							
												 plan *pln, const problem *p);
							 | 
						||
| 
								 | 
							
								IFFTW_EXTERN int X(ialignment_of)(R *p);
							 | 
						||
| 
								 | 
							
								unsigned X(hash)(const char *s);
							 | 
						||
| 
								 | 
							
								INT X(nbuf)(INT n, INT vl, INT maxnbuf);
							 | 
						||
| 
								 | 
							
								int X(nbuf_redundant)(INT n, INT vl, size_t which, 
							 | 
						||
| 
								 | 
							
										      const INT *maxnbuf, size_t nmaxnbuf);
							 | 
						||
| 
								 | 
							
								INT X(bufdist)(INT n, INT vl);
							 | 
						||
| 
								 | 
							
								int X(toobig)(INT n);
							 | 
						||
| 
								 | 
							
								int X(ct_uglyp)(INT min_n, INT v, INT n, INT r);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if HAVE_SIMD
							 | 
						||
| 
								 | 
							
								R *X(taint)(R *p, INT s);
							 | 
						||
| 
								 | 
							
								R *X(join_taint)(R *p1, R *p2);
							 | 
						||
| 
								 | 
							
								#define TAINT(p, s) X(taint)(p, s)
							 | 
						||
| 
								 | 
							
								#define UNTAINT(p) ((R *) (((uintptr_t) (p)) & ~(uintptr_t)3))
							 | 
						||
| 
								 | 
							
								#define TAINTOF(p) (((uintptr_t)(p)) & 3)
							 | 
						||
| 
								 | 
							
								#define JOIN_TAINT(p1, p2) X(join_taint)(p1, p2)
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#define TAINT(p, s) (p)
							 | 
						||
| 
								 | 
							
								#define UNTAINT(p) (p)
							 | 
						||
| 
								 | 
							
								#define TAINTOF(p) 0
							 | 
						||
| 
								 | 
							
								#define JOIN_TAINT(p1, p2) p1
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define ASSERT_ALIGNED_DOUBLE  /*unused, legacy*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*-----------------------------------------------------------------------*/
							 | 
						||
| 
								 | 
							
								/* macros used in codelets to reduce source code size */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								typedef R E;  /* internal precision of codelets. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(FFTW_LDOUBLE)
							 | 
						||
| 
								 | 
							
								#  define K(x) ((E) x##L)
							 | 
						||
| 
								 | 
							
								#elif defined(FFTW_QUAD)
							 | 
						||
| 
								 | 
							
								#  define K(x) ((E) x##Q)
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#  define K(x) ((E) x)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#define DK(name, value) const E name = K(value)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* FMA macros */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__) || defined(_POWER))
							 | 
						||
| 
								 | 
							
								/* The obvious expression a * b + c does not work.  If both x = a * b
							 | 
						||
| 
								 | 
							
								   + c and y = a * b - c appear in the source, gcc computes t = a * b,
							 | 
						||
| 
								 | 
							
								   x = t + c, y = t - c, thus destroying the fma.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   This peculiar coding seems to do the right thing on all of
							 | 
						||
| 
								 | 
							
								   gcc-2.95, gcc-3.1, gcc-3.2, and gcc-3.3.  It does the right thing
							 | 
						||
| 
								 | 
							
								   on gcc-3.4 -fno-web (because the ``web'' pass splits the variable
							 | 
						||
| 
								 | 
							
								   `x' for the single-assignment form).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   However, gcc-4.0 is a formidable adversary which succeeds in
							 | 
						||
| 
								 | 
							
								   pessimizing two fma's into one multiplication and two additions.
							 | 
						||
| 
								 | 
							
								   It does it very early in the game---before the optimization passes
							 | 
						||
| 
								 | 
							
								   even start.  The only real workaround seems to use fake inline asm
							 | 
						||
| 
								 | 
							
								   such as
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								     asm ("# confuse gcc %0" : "=f"(a) : "0"(a));
							 | 
						||
| 
								 | 
							
								     return a * b + c;
							 | 
						||
| 
								 | 
							
								     
							 | 
						||
| 
								 | 
							
								   in each of the FMA, FMS, FNMA, and FNMS functions.  However, this
							 | 
						||
| 
								 | 
							
								   does not solve the problem either, because two equal asm statements
							 | 
						||
| 
								 | 
							
								   count as a common subexpression!  One must use *different* fake asm
							 | 
						||
| 
								 | 
							
								   statements:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   in FMA:
							 | 
						||
| 
								 | 
							
								     asm ("# confuse gcc for fma %0" : "=f"(a) : "0"(a));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   in FMS:
							 | 
						||
| 
								 | 
							
								     asm ("# confuse gcc for fms %0" : "=f"(a) : "0"(a));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   etc.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   After these changes, gcc recalcitrantly generates the fma that was
							 | 
						||
| 
								 | 
							
								   in the source to begin with.  However, the extra asm() cruft
							 | 
						||
| 
								 | 
							
								   confuses other passes of gcc, notably the instruction scheduler.
							 | 
						||
| 
								 | 
							
								   (Of course, one could also generate the fma directly via inline
							 | 
						||
| 
								 | 
							
								   asm, but this confuses the scheduler even more.)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   Steven and I have submitted more than one bug report to the gcc
							 | 
						||
| 
								 | 
							
								   mailing list over the past few years, to no effect.  Thus, I give
							 | 
						||
| 
								 | 
							
								   up.  gcc-4.0 can go to hell.  I'll wait at least until gcc-4.3 is
							 | 
						||
| 
								 | 
							
								   out before touching this crap again.
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								static __inline__ E FMA(E a, E b, E c)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								     E x = a * b;
							 | 
						||
| 
								 | 
							
								     x = x + c;
							 | 
						||
| 
								 | 
							
								     return x;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static __inline__ E FMS(E a, E b, E c)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								     E x = a * b;
							 | 
						||
| 
								 | 
							
								     x = x - c;
							 | 
						||
| 
								 | 
							
								     return x;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static __inline__ E FNMA(E a, E b, E c)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								     E x = a * b;
							 | 
						||
| 
								 | 
							
								     x = - (x + c);
							 | 
						||
| 
								 | 
							
								     return x;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static __inline__ E FNMS(E a, E b, E c)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								     E x = a * b;
							 | 
						||
| 
								 | 
							
								     x = - (x - c);
							 | 
						||
| 
								 | 
							
								     return x;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#define FMA(a, b, c) (((a) * (b)) + (c))
							 | 
						||
| 
								 | 
							
								#define FMS(a, b, c) (((a) * (b)) - (c))
							 | 
						||
| 
								 | 
							
								#define FNMA(a, b, c) (- (((a) * (b)) + (c)))
							 | 
						||
| 
								 | 
							
								#define FNMS(a, b, c) ((c) - ((a) * (b)))
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef __cplusplus
							 | 
						||
| 
								 | 
							
								}  /* extern "C" */
							 | 
						||
| 
								 | 
							
								#endif /* __cplusplus */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* __IFFTW_H__ */
							 |