├── .gitignore ├── FItSNE.sln ├── FItSNE.vcxproj ├── LICENSE.txt ├── README.md ├── bin └── .gitignore ├── examples ├── test.R ├── test.ipynb └── test.m ├── fast_tsne.R ├── fast_tsne.m ├── fast_tsne.py └── src ├── annoylib.h ├── kissrandom.h ├── nbodyfft.cpp ├── nbodyfft.h ├── parallel_for.h ├── progress_bar ├── LICENSE └── ProgressBar.hpp ├── sptree.cpp ├── sptree.h ├── time_code.h ├── tsne.cpp ├── tsne.h ├── vptree.h └── winlibs ├── fftw ├── fftw3.f ├── fftw3.f03 ├── fftw3.h ├── fftw3l.f03 ├── fftw3q.f03 ├── ffwt_license-and-copyright.html ├── libfftw3-3.def ├── libfftw3-3.dll ├── libfftw3-3.exp ├── libfftw3-3.lib ├── libfftw3f-3.def ├── libfftw3f-3.dll ├── libfftw3f-3.exp ├── libfftw3f-3.lib ├── libfftw3l-3.def ├── libfftw3l-3.dll ├── libfftw3l-3.exp └── libfftw3l-3.lib ├── fftw3.h ├── mman.c ├── mman.h ├── stdafx.cpp ├── stdafx.h ├── targetver.h └── unistd.h /.gitignore: -------------------------------------------------------------------------------- 1 | bin/* 2 | *.m~ 3 | *.dat 4 | .DS_Store 5 | *.sw* 6 | .idea/ 7 | *.cmake 8 | CMakeCache.txt 9 | *.cbp 10 | CMakeFiles/ 11 | cmake-build-debug/ 12 | Makefile 13 | -------------------------------------------------------------------------------- /FItSNE.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FItSNE", "FItSNE.vcxproj", "{D7401C22-FC52-4657-86D0-DBEBE8DCE006}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D7401C22-FC52-4657-86D0-DBEBE8DCE006}.Debug|x64.ActiveCfg = Debug|x64 15 | {D7401C22-FC52-4657-86D0-DBEBE8DCE006}.Debug|x64.Build.0 = Debug|x64 16 | {D7401C22-FC52-4657-86D0-DBEBE8DCE006}.Release|x64.ActiveCfg = Release|x64 17 | {D7401C22-FC52-4657-86D0-DBEBE8DCE006}.Release|x64.Build.0 = Release|x64 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /FItSNE.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {D7401C22-FC52-4657-86D0-DBEBE8DCE006} 23 | Win32Proj 24 | FItSNE 25 | 8.1 26 | 27 | 28 | 29 | Application 30 | true 31 | v140 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v140 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v140 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v140 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | true 74 | 75 | 76 | true 77 | 78 | 79 | false 80 | 81 | 82 | false 83 | 84 | 85 | 86 | NotUsing 87 | Level3 88 | Disabled 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | libfftw3-3.lib;libfftw3f-3.lib;libfftw3l-3.lib;%(AdditionalDependencies) 96 | src\winlibs\fftw;%(AdditionalLibraryDirectories) 97 | 98 | 99 | 100 | 101 | NotUsing 102 | Level3 103 | Disabled 104 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | true 106 | src\winlibs\fftw;%(AdditionalIncludeDirectories) 107 | 108 | 109 | Console 110 | true 111 | src\winlibs\fftw;%(AdditionalLibraryDirectories) 112 | libfftw3-3.lib;libfftw3f-3.lib;libfftw3l-3.lib;%(AdditionalDependencies) 113 | 114 | 115 | 116 | 117 | Level3 118 | NotUsing 119 | MaxSpeed 120 | true 121 | true 122 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 123 | true 124 | 125 | 126 | Console 127 | true 128 | true 129 | true 130 | libfftw3-3.lib;libfftw3f-3.lib;libfftw3l-3.lib;%(AdditionalDependencies) 131 | src\winlibs\fftw;%(AdditionalLibraryDirectories) 132 | 133 | 134 | 135 | 136 | Level3 137 | NotUsing 138 | MaxSpeed 139 | true 140 | true 141 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 142 | true 143 | src\winlibs\fftw;%(AdditionalIncludeDirectories) 144 | 145 | 146 | Console 147 | true 148 | true 149 | true 150 | src\winlibs\fftw;%(AdditionalLibraryDirectories) 151 | libfftw3-3.lib;libfftw3f-3.lib;libfftw3l-3.lib;%(AdditionalDependencies) 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | NotUsing 172 | NotUsing 173 | NotUsing 174 | NotUsing 175 | 176 | 177 | 178 | 179 | Create 180 | Create 181 | Create 182 | Create 183 | 184 | 185 | 186 | 187 | 188 | 189 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Different attribution requirements and conditions apply to different files in this repository: 2 | 3 | ======================================================================================== 4 | The following license applies to the following files in the src directory: tsne.cpp, tsne.h, sptree.cpp, sptree.h, vptree.h 5 | 6 | Copyright (c) 2014, Laurens van der Maaten (Delft University of Technology) 7 | All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 1. Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 3. All advertising materials mentioning features or use of this software 17 | must display the following acknowledgement: 18 | This product includes software developed by the Delft University of Technology. 19 | 4. Neither the name of the Delft University of Technology nor the names of 20 | its contributors may be used to endorse or promote products derived from 21 | this software without specific prior written permission. 22 | 23 | THIS SOFTWARE IS PROVIDED BY LAURENS VAN DER MAATEN ''AS IS'' AND ANY EXPRESS 24 | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 26 | EVENT SHALL LAURENS VAN DER MAATEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 31 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 32 | OF SUCH DAMAGE. 33 | 34 | 35 | ======================================================================================== 36 | The following license applies to the following files in the src directory: nbodyfft.h, nbodyfft.cpp, parallel_for.h, time_code.h 37 | 38 | (The MIT License) 39 | 40 | Copyright (c) [2019] [George Linderman] 41 | 42 | Permission is hereby granted, free of charge, to any person obtaining a copy 43 | of this software and associated documentation files (the "Software"), to deal 44 | in the Software without restriction, including without limitation the rights 45 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 46 | copies of the Software, and to permit persons to whom the Software is 47 | furnished to do so, subject to the following conditions: 48 | 49 | The above copyright notice and this permission notice shall be included in all 50 | copies or substantial portions of the Software. 51 | 52 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 53 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 54 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 55 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 56 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 57 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 58 | SOFTWARE. 59 | 60 | ======================================================================================== 61 | The following license applies to following files in the progress_bar directory: ProgressBar.hpp 62 | 63 | (The MIT License) 64 | 65 | Copyright (c) 2016 Prakhar Srivastav 66 | 67 | Permission is hereby granted, free of charge, to any person obtaining 68 | a copy of this software and associated documentation files (the 69 | 'Software'), to deal in the Software without restriction, including 70 | without limitation the rights to use, copy, modify, merge, publish, 71 | distribute, sublicense, and/or sell copies of the Software, and to 72 | permit persons to whom the Software is furnished to do so, subject to 73 | the following conditions: 74 | 75 | The above copyright notice and this permission notice shall be 76 | included in all copies or substantial portions of the Software. 77 | 78 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 79 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 80 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 81 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 82 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 83 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 84 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 85 | 86 | ======================================================================================== 87 | The following license applies to following files in the src directory: annoylib.h 88 | 89 | 90 | Copyright (c) 2013 Spotify AB 91 | 92 | Licensed under the Apache License, Version 2.0 (the "License"); you may not 93 | use this file except in compliance with the License. You may obtain a copy of 94 | the License at 95 | 96 | http://www.apache.org/licenses/LICENSE-2.0 97 | 98 | Unless required by applicable law or agreed to in writing, software 99 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 100 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 101 | License for the specific language governing permissions and limitations under 102 | the License. 103 | 104 | ======================================================================================== 105 | The following license applies to all files in the src/winlibs/fftw directory 106 | 107 | FFTW is Copyright © 2003, 2007-11 Matteo Frigo, Copyright © 2003, 2007-11 108 | Massachusetts Institute of Technology. 109 | 110 | FFTW is free software; you can redistribute it and/or modify it under the terms 111 | of the GNU General Public License as published by the Free Software Foundation; 112 | either version 2 of the License, or (at your option) any later version. 113 | 114 | This program is distributed in the hope that it will be useful, but WITHOUT ANY 115 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 116 | PARTICULAR PURPOSE. See the GNU General Public License for more details. 117 | 118 | You should have received a copy of the GNU General Public License along with 119 | this program; if not, write to the Free Software Foundation, Inc., 51 Franklin 120 | Street, Fifth Floor, Boston, MA 02110-1301 USA You can also find the GPL on the 121 | GNU web site. 122 | 123 | In addition, we kindly ask you to acknowledge FFTW and its authors in any 124 | program or publication in which you use FFTW. (You are not required to do so; 125 | it is up to your common sense to decide whether you want to comply with this 126 | request or not.) For general publications, we suggest referencing: Matteo Frigo 127 | and Steven G. Johnson, “The design and implementation of FFTW3,” Proc. IEEE 93 128 | (2), 216–231 (2005). 129 | 130 | Non-free versions of FFTW are available under terms different from those of the 131 | General Public License. (e.g. they do not require you to accompany any object 132 | code using FFTW with the corresponding source code.) For these alternative 133 | terms you must purchase a license from MIT’s Technology Licensing Office. Users 134 | interested in such a license should contact us (fftw@fftw.org) for more 135 | information. 136 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FFT-accelerated Interpolation-based t-SNE (FIt-SNE) 2 | ## Introduction 3 | t-Stochastic Neighborhood Embedding ([t-SNE](https://lvdmaaten.github.io/tsne/)) is a highly successful method for dimensionality reduction and visualization of high dimensional datasets. A popular [implementation](https://github.com/lvdmaaten/bhtsne) of t-SNE uses the Barnes-Hut algorithm to approximate the gradient at each iteration of gradient descent. We accelerated this implementation as follows: 4 | 5 | * Computation of the N-body Simulation: Instead of approximating the N-body simulation using Barnes-Hut, we interpolate onto an equispaced grid and use FFT to perform the convolution, dramatically reducing the time to compute the gradient at each iteration of gradient descent. See the [this](http://gauss.math.yale.edu/~gcl22/blog/numerics/low-rank/t-sne/2018/01/11/low-rank-kernels.html) post for some intuition on how it works. 6 | * Computation of Input Similarities: Instead of computing nearest neighbors using vantage-point trees, we approximate nearest neighbors using the [Annoy](https://github.com/spotify/annoy) library. The neighbor lookups are multithreaded to take advantage of machines with multiple cores. Using "near" neighbors as opposed to strictly "nearest" neighbors is faster, but also has a smoothing effect, which can be useful for embedding some datasets (see [Linderman et al. (2017)](https://arxiv.org/abs/1711.04712)). If subtle detail is required (e.g. in identifying small clusters), then use vantage-point trees (which is also multithreaded in this implementation). 7 | 8 | 9 | Check out our [paper](https://www.nature.com/articles/s41592-018-0308-4) or [preprint](https://arxiv.org/abs/1712.09005) for more details and some benchmarks. 10 | 11 | ## Features 12 | Additionally, this implementation includes the following features: 13 | * Early exaggeration: In [Linderman and Steinerberger (2018)](https://epubs.siam.org/doi/abs/10.1137/18M1216134), we showed that appropriately choosing the early exaggeration coefficient can lead to improved embedding of swissrolls and other synthetic datasets. Early exaggeration is built into all t-SNE implementations; here we highlight its importance as a parameter. 14 | * Late exaggeration: Increasing the exaggeration coefficient late in the optimization process can improve separation of the clusters. [Kobak and Berens (2019)](https://www.nature.com/articles/s41467-019-13056-x) suggest starting late exaggeration immediately following early exaggeration. 15 | * Initialization: Custom initialization can be provided from Python/Matlab/R. As suggested by [Kobak and Berens (2019)](https://www.nature.com/articles/s41467-019-13056-x), initializing t-SNE with the first two principal components (scaled to have standard deviation 0.0001) results in an embedding which often preserves the global structure more effectively than the default random normalization. See there for other initialisation tricks. 16 | * Variable degrees of freedom: [Kobak et al. (2019)](https://ecmlpkdd2019.org/downloads/paper/327.pdf) show that decreasing the degree of freedom (df) of the t-distribution (resulting in heavier tails) reveals fine structure that is not visible in standard t-SNE. 17 | * Perplexity combination: The perplexity parameter determines the width of the Gaussian kernel, such that small perplexity values uncover local structure while larger values reveal global structure. [Kobak and Berens (2019)](https://www.nature.com/articles/s41467-019-13056-x) show that using combination of several perplexity values, resulting in a multi-scale embedding, can be useful. 18 | * All optimisation parameters can be controlled from Python/Matlab/R. For example, [Belkina et al. (2019)](https://www.nature.com/articles/s41467-019-13055-y) highlight the importance of increasing the learning rate when embedding large data sets. 19 | 20 | 21 | ## Installation 22 | R, Matlab, and Python wrappers are `fast_tsne.R`, `fast_tsne.m`, and `fast_tsne.py` respectively. Each of these wrappers can be used after installing FFTW and compiling the C++ code, as below. [Gioele La Manno](https://twitter.com/GioeleLaManno) implemented a Python (Cython) wrapper, which is available on PyPI [here](https://pypi.python.org/pypi/fitsne). 23 | 24 | **Note:** If you update to a new version of FIt-SNE using `git pull`, be sure to recompile. 25 | 26 | ### OSX and Linux 27 | The only prerequisite is [FFTW](http://www.fftw.org/), which can be downloaded and installed from the website. Then, from the root directory compile the code as: 28 | ```bash 29 | g++ -std=c++11 -O3 src/sptree.cpp src/tsne.cpp src/nbodyfft.cpp -o bin/fast_tsne -pthread -lfftw3 -lm -Wno-address-of-packed-member 30 | ``` 31 | See [here](https://github.com/KlugerLab/FIt-SNE/issues/35) for instructions in case one does not have `sudo` rights (one can install `FFTW` in the home directory and provide its path to `g++`). 32 | 33 | Check out `examples/` for usage. The [Python demo notebook](https://github.com/KlugerLab/FIt-SNE/blob/master/examples/test.ipynb) walks one through the most of the available options using the MNIST data set. 34 | 35 | 36 | ### Windows 37 | A Windows binary is available [here](https://github.com/KlugerLab/FIt-SNE/releases/download/v1.2.1/FItSNE-Windows-1.2.1.zip). Please extract to the `bin/` folder, and you should be all set. 38 | 39 | If you would like to compile it yourself see below. The code has been currently tested with MS Visual Studio 2015 (i.e., MS Visual Studio Version 14). 40 | 41 | 1. First open the provided FItSNE solution (FItSNE.sln) using MS Visual Studio and build the Release configuration. 42 | 2. Copy the binary file ( e.g. `x64/Release/FItSNE.exe`) generated by the build process to the `bin/` folder 43 | 3. For Windows, we have added all dependencies, including the [FFTW library](http://www.fftw.org/), which is distributed under the GNU General Public License. For the binary to find the FFTW DLLs, you need to either add `src/winlibs/fftw/` to your PATH, or to copy the DLLs into the `bin/` directory. 44 | 45 | As of this commit, only the R wrapper properly calls the Windows executable. The Python and Matlab wrappers can be trivially changed to call it (just changing `bin/fast_tsne` to `bin/FItSNE.exe` in the code), and will be changed in future commits. 46 | 47 | Many thanks to [Josef Spidlen](https://github.com/jspidlen) for this Windows implementation! 48 | 49 | ## Acknowledgements and References 50 | We are grateful for members of the community who have [contributed](https://github.com/KlugerLab/FIt-SNE/graphs/contributors) to improving FIt-SNE, especially [Dmitry Kobak](https://github.com/dkobak), [Pavlin Poličar](https://github.com/pavlin-policar), and [Josef Spidlen](https://github.com/jspidlen). 51 | 52 | If you use FIt-SNE, please cite: 53 | 54 | George C. Linderman, Manas Rachh, Jeremy G. Hoskins, Stefan Steinerberger, Yuval Kluger. (2019). Fast interpolation-based t-SNE for improved visualization of single-cell RNA-seq data. Nature Methods. ([link](https://www.nature.com/articles/s41592-018-0308-4)) 55 | 56 | Our implementation is derived from the Barnes-Hut implementation: 57 | 58 | Laurens van der Maaten (2014). Accelerating t-SNE using tree-based algorithms. Journal of Machine Learning Research, 15(1):3221–3245. ([link](https://dl.acm.org/citation.cfm?id=2627435.2697068)) 59 | 60 | -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /examples/test.R: -------------------------------------------------------------------------------- 1 | # Note: the chdir=T argument to source() is necessary if running FIt-SNE outside of the the root directory of FIt-SNE 2 | 3 | source('../fast_tsne.R', chdir=T) 4 | 5 | # Using Iris dataset 6 | 7 | iris_unique <- unique(iris) # Remove duplicates 8 | X <- as.matrix(iris_unique[,1:4]) # Run TSNE 9 | 10 | Y_fft <- fftRtsne(X); 11 | plot(Y_fft,col=iris_unique$Species) # Plot the result 12 | 13 | 14 | # And now using a toy dataset and d=1 15 | 16 | require(MASS); 17 | N <- 1E4; 18 | d <- 3; 19 | input_data <- rbind(mvrnorm(n = N/2, rep(0, d), diag(d)), 20 | mvrnorm(n = N/2, rep(100, d), diag(d))) 21 | Y2 <- fftRtsne(input_data, 1, max_iter = 400, start_late_exag_iter=300, late_exag_coeff=10); 22 | plot(Y2[,1],runif(length(Y2)),col=c(rep(1,N/2), rep(2,N/2))) # Plot the result 23 | -------------------------------------------------------------------------------- /examples/test.m: -------------------------------------------------------------------------------- 1 | % This should be the path to the FIt-SNE folder where fast_tsne.m is located 2 | addpath('../') 3 | 4 | % Generate a toy dataset 5 | 6 | dim = 3; 7 | sigma_0 = .0001; 8 | cluster_num = 2; 9 | cluster_size = 1E4; 10 | 11 | X_clusters = []; 12 | col_clusters = repmat(1:cluster_num,cluster_size,1); 13 | col_clusters = col_clusters(:); 14 | 15 | for i = 1:cluster_num 16 | X_clusters = [X_clusters; mvnrnd(rand(dim,1)', diag(sigma_0*ones(dim,1)), cluster_size)]; 17 | end 18 | 19 | N_clusters = size(X_clusters,1); 20 | 21 | figure(19988) 22 | subplot(121) 23 | scatter3(X_clusters(:,1), X_clusters(:,2), X_clusters(:,3),10, col_clusters, 'filled'); 24 | title('Original Data') 25 | 26 | % Run t-SNE 27 | 28 | clear opts 29 | opts.max_iter = 400; 30 | cluster_firstphase = fast_tsne(X_clusters, opts); 31 | 32 | subplot(122) 33 | scatter(cluster_firstphase(:,1), cluster_firstphase(:,2), 10, col_clusters, 'filled'); 34 | title('After t-SNE') 35 | colormap(lines(cluster_num)) 36 | -------------------------------------------------------------------------------- /fast_tsne.R: -------------------------------------------------------------------------------- 1 | # Note: this script should be sourced as: source('', chdir=T) 2 | 3 | FAST_TSNE_SCRIPT_DIR <<- getwd() 4 | 5 | message("FIt-SNE R wrapper loading.") 6 | message("FIt-SNE root directory was set to ", FAST_TSNE_SCRIPT_DIR) 7 | 8 | # Compute FIt-SNE of a dataset 9 | # dims - dimensionality of the embedding. Default 2. 10 | # perplexity - perplexity is used to determine the 11 | # bandwidth of the Gaussian kernel in the input 12 | # space. Default 30. 13 | # theta - Set to 0 for exact. If non-zero, then will use either 14 | # Barnes Hut or FIt-SNE based on nbody_algo. If Barnes Hut, then 15 | # this determins the accuracy of BH approximation. 16 | # Default 0.5. 17 | # max_iter - Number of iterations of t-SNE to run. 18 | # Default 750. 19 | # fft_not_bh - if theta is nonzero, this determines whether to 20 | # use FIt-SNE or Barnes Hut approximation. Default is FIt-SNE. 21 | # set to be True for FIt-SNE 22 | # ann_not_vptree - use vp-trees (as in bhtsne) or approximate nearest neighbors (default). 23 | # set to be True for approximate nearest neighbors 24 | # exaggeration_factor - coefficient for early exaggeration 25 | # (>1). Default 12. 26 | # no_momentum_during_exag - Set to 0 to use momentum 27 | # and other optimization tricks. 1 to do plain,vanilla 28 | # gradient descent (useful for testing large exaggeration 29 | # coefficients) 30 | # stop_early_exag_iter - When to switch off early exaggeration. 31 | # Default 250. 32 | # start_late_exag_iter - When to start late exaggeration. 'auto' means 33 | # that late exaggeration is not used, unless late_exag_coeff>0. In that 34 | # case, start_late_exag_iter is set to stop_early_exag_iter. Otherwise, 35 | # set to equal the iteration at which late exaggeration should begin. 36 | # Default 'auto' 37 | # late_exag_coeff - Late exaggeration coefficient. 38 | # Set to -1 to not use late exaggeration. 39 | # Default -1 40 | # learning_rate - Set to desired learning rate or 'auto', which 41 | # sets learning rate to N/exaggeration_factor where N is the sample size, or to 200 if 42 | # N/exaggeration_factor < 200. 43 | # Default 'auto' 44 | # max_step_norm - Maximum distance that a point is allowed to move on 45 | # one iteration. Larger steps are clipped to this value. This prevents 46 | # possible instabilities during gradient descent. Set to -1 to switch it 47 | # off. Default: 5 48 | # nterms - If using FIt-SNE, this is the number of 49 | # interpolation points per sub-interval 50 | # intervals_per_integer - See min_num_intervals 51 | # min_num_intervals - Let maxloc = ceil(max(max(X))) 52 | # and minloc = floor(min(min(X))). i.e. the points are in 53 | # a [minloc]^no_dims by [maxloc]^no_dims interval/square. 54 | # The number of intervals in each dimension is either 55 | # min_num_intervals or ceil((maxloc - 56 | # minloc)/intervals_per_integer), whichever is 57 | # larger. min_num_intervals must be an integer >0, 58 | # and intervals_per_integer must be >0. Default: 59 | # min_num_intervals=50, intervals_per_integer = 60 | # 1 61 | # 62 | # sigma - Fixed sigma value to use when perplexity==-1 63 | # Default -1 (None) 64 | # K - Number of nearest neighbours to get when using fixed sigma 65 | # Default -30 (None) 66 | # 67 | # initialization - 'pca', 'random', or N x no_dims array to intialize the solution. 68 | # Default: 'pca' 69 | # 70 | # load_affinities - 71 | # If 1, input similarities are loaded from a file and not computed 72 | # If 2, input similarities are saved into a file. 73 | # If 0, affinities are neither saved nor loaded 74 | # 75 | # perplexity_list - if perplexity==0 then perplexity combination will 76 | # be used with values taken from perplexity_list. Default: NULL 77 | # df - Degree of freedom of t-distribution, must be greater than 0. 78 | # Values smaller than 1 correspond to heavier tails, which can often 79 | # resolve substructure in the embedding. See Kobak et al. (2019) for 80 | # details. Default is 1.0 81 | # 82 | fftRtsne <- function(X, 83 | dims = 2, perplexity = 30, theta = 0.5, 84 | max_iter = 750, 85 | fft_not_bh = TRUE, 86 | ann_not_vptree = TRUE, 87 | stop_early_exag_iter = 250, 88 | exaggeration_factor = 12.0, no_momentum_during_exag = FALSE, 89 | start_late_exag_iter = -1, late_exag_coeff = 1.0, 90 | mom_switch_iter = 250, momentum = 0.5, final_momentum = 0.8, learning_rate = 'auto', 91 | n_trees = 50, search_k = -1, rand_seed = -1, 92 | nterms = 3, intervals_per_integer = 1, min_num_intervals = 50, 93 | K = -1, sigma = -30, initialization = 'pca',max_step_norm = 5, 94 | data_path = NULL, result_path = NULL, 95 | load_affinities = NULL, 96 | fast_tsne_path = NULL, nthreads = 0, perplexity_list = NULL, 97 | get_costs = FALSE, df = 1.0) { 98 | 99 | version_number <- '1.2.1' 100 | 101 | if (is.null(fast_tsne_path)) { 102 | if (.Platform$OS.type == "unix") { 103 | fast_tsne_path <- file.path(FAST_TSNE_SCRIPT_DIR, "bin", "fast_tsne") 104 | } else { 105 | fast_tsne_path <- file.path(FAST_TSNE_SCRIPT_DIR, "bin", "FItSNE.exe") 106 | } 107 | } 108 | 109 | if (is.null(data_path)) { 110 | data_path <- tempfile(pattern = 'fftRtsne_data_', fileext = '.dat') 111 | } 112 | if (is.null(result_path)) { 113 | result_path <- tempfile(pattern = 'fftRtsne_result_', fileext = '.dat') 114 | } 115 | if (is.null(fast_tsne_path)) { 116 | fast_tsne_path <- system2('which', 'fast_tsne', stdout = TRUE) 117 | } 118 | fast_tsne_path <- normalizePath(fast_tsne_path) 119 | if (!file_test('-x', fast_tsne_path)) { 120 | stop(fast_tsne_path, " does not exist or is not executable; check your fast_tsne_path parameter") 121 | } 122 | 123 | is.wholenumber <- function(x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol 124 | 125 | if (!is.numeric(theta) || (theta < 0.0) || (theta > 1.0) ) { stop("Incorrect theta.")} 126 | if (nrow(X) - 1 < 3 * perplexity) { stop("Perplexity is too large.")} 127 | if (!is.matrix(X)) { stop("Input X is not a matrix")} 128 | if (!(max_iter > 0)) { stop("Incorrect number of iterations.")} 129 | if (!is.wholenumber(stop_early_exag_iter) || stop_early_exag_iter < 0) { stop("stop_early_exag_iter should be a positive integer")} 130 | if (!is.numeric(exaggeration_factor)) { stop("exaggeration_factor should be numeric")} 131 | if (!is.numeric(df)) { stop("df should be numeric")} 132 | if (!is.wholenumber(dims) || dims <= 0) { stop("Incorrect dimensionality.")} 133 | if (search_k == -1) { 134 | if (perplexity > 0) { 135 | search_k <- n_trees * perplexity * 3 136 | } else if (perplexity == 0) { 137 | search_k <- n_trees * max(perplexity_list) * 3 138 | } else { 139 | search_k <- n_trees * K 140 | } 141 | } 142 | 143 | if (is.character(learning_rate) && learning_rate =='auto') { 144 | learning_rate = max(200, nrow(X)/exaggeration_factor) 145 | } 146 | if (is.character(start_late_exag_iter) && start_late_exag_iter =='auto') { 147 | if (late_exag_coeff > 0) { 148 | start_late_exag_iter = stop_early_exag_iter 149 | }else { 150 | start_late_exag_iter = -1 151 | } 152 | } 153 | 154 | if (is.character(initialization) && initialization =='pca') { 155 | if (rand_seed != -1) { 156 | set.seed(rand_seed) 157 | } 158 | if ("rsvd" %in% utils::installed.packages()) { 159 | message('Using rsvd() to compute the top PCs for initialization.') 160 | X_c <- scale(X, center=T, scale=F) 161 | rsvd_out <- rsvd::rsvd(X_c, k=dims) 162 | X_top_pcs <- rsvd_out$u %*% diag(rsvd_out$d, nrow=dims) 163 | }else if("irlba" %in% utils::installed.packages()) { 164 | message('Using irlba() to compute the top PCs for initialization.') 165 | X_colmeans <- colMeans(X) 166 | irlba_out <- irlba::irlba(X,nv=dims, center=X_colmeans) 167 | X_top_pcs <- irlba_out$u %*% diag(irlba_out$d, nrow=dims) 168 | }else{ 169 | stop("By default, FIt-SNE initializes the embedding with the 170 | top PCs. We use either rsvd or irlba for fast computation. 171 | To use this functionality, please install the rsvd package 172 | with install.packages('rsvd') or the irlba package with 173 | install.packages('ilrba'). Otherwise, set initialization 174 | to NULL for random initialization, or any N by dims matrix 175 | for custom initialization.") 176 | } 177 | initialization <- 0.0001*(X_top_pcs/sd(X_top_pcs[,1])) 178 | 179 | }else if (is.character(initialization) && initialization == 'random'){ 180 | message('Random initialization') 181 | initialization = NULL 182 | } 183 | 184 | if (fft_not_bh) { 185 | nbody_algo <- 2 186 | } else { 187 | nbody_algo <- 1 188 | } 189 | 190 | if (is.null(load_affinities)) { 191 | load_affinities <- 0 192 | } else { 193 | if (load_affinities == 'load') { 194 | load_affinities <- 1 195 | } else if (load_affinities == 'save') { 196 | load_affinities <- 2 197 | } else { 198 | load_affinities <- 0 199 | } 200 | } 201 | 202 | if (ann_not_vptree) { 203 | knn_algo <- 1 204 | } else { 205 | knn_algo <- 2 206 | } 207 | tX <- as.numeric(t(X)) 208 | 209 | f <- file(data_path, "wb") 210 | n <- nrow(X) 211 | D <- ncol(X) 212 | writeBin(as.integer(n), f, size = 4) 213 | writeBin(as.integer(D), f, size = 4) 214 | writeBin(as.numeric(theta), f, size = 8) #theta 215 | writeBin(as.numeric(perplexity), f, size = 8) 216 | 217 | if (perplexity == 0) { 218 | writeBin(as.integer(length(perplexity_list)), f, size = 4) 219 | writeBin(perplexity_list, f) 220 | } 221 | 222 | writeBin(as.integer(dims), f, size = 4) 223 | writeBin(as.integer(max_iter), f, size = 4) 224 | writeBin(as.integer(stop_early_exag_iter), f, size = 4) 225 | writeBin(as.integer(mom_switch_iter), f, size = 4) 226 | writeBin(as.numeric(momentum), f, size = 8) 227 | writeBin(as.numeric(final_momentum), f, size = 8) 228 | writeBin(as.numeric(learning_rate), f, size = 8) 229 | writeBin(as.numeric(max_step_norm), f, size = 8) 230 | writeBin(as.integer(K), f, size = 4) #K 231 | writeBin(as.numeric(sigma), f, size = 8) #sigma 232 | writeBin(as.integer(nbody_algo), f, size = 4) #not barnes hut 233 | writeBin(as.integer(knn_algo), f, size = 4) 234 | writeBin(as.numeric(exaggeration_factor), f, size = 8) #compexag 235 | writeBin(as.integer(no_momentum_during_exag), f, size = 4) 236 | writeBin(as.integer(n_trees), f, size = 4) 237 | writeBin(as.integer(search_k), f, size = 4) 238 | writeBin(as.integer(start_late_exag_iter), f, size = 4) 239 | writeBin(as.numeric(late_exag_coeff), f, size = 8) 240 | 241 | writeBin(as.integer(nterms), f, size = 4) 242 | writeBin(as.numeric(intervals_per_integer), f, size = 8) 243 | writeBin(as.integer(min_num_intervals), f, size = 4) 244 | writeBin(tX, f) 245 | writeBin(as.integer(rand_seed), f, size = 4) 246 | writeBin(as.numeric(df), f, size = 8) 247 | writeBin(as.integer(load_affinities), f, size = 4) 248 | if (!is.null(initialization) ) { writeBin( c(t(initialization)), f) } 249 | close(f) 250 | 251 | flag <- system2(command = fast_tsne_path, 252 | args = c(version_number, data_path, result_path, nthreads)) 253 | if (flag != 0) { 254 | stop('tsne call failed') 255 | } 256 | f <- file(result_path, "rb") 257 | n <- readBin(f, integer(), n = 1, size = 4) 258 | d <- readBin(f, integer(), n = 1, size = 4) 259 | Y <- readBin(f, numeric(), n = n * d) 260 | Y <- t(matrix(Y, nrow = d)) 261 | if (get_costs) { 262 | readBin(f, integer(), n = 1, size = 4) 263 | costs <- readBin(f, numeric(), n = max_iter, size = 8) 264 | Yout <- list(Y = Y, costs = costs) 265 | } else { 266 | Yout <- Y 267 | } 268 | close(f) 269 | file.remove(data_path) 270 | file.remove(result_path) 271 | Yout 272 | } 273 | -------------------------------------------------------------------------------- /fast_tsne.m: -------------------------------------------------------------------------------- 1 | function [mappedX, costs, initialError] = fast_tsne(X, opts) 2 | %FAST_TSNE Runs the C++ implementation of FMM t-SNE 3 | % 4 | % mappedX = fast_tsne(X, opts, initial_data) 5 | % X - Input dataset, rows are observations and columns are 6 | % variables 7 | % opts - a struct with the following possible parameters 8 | % opts.no_dims - dimensionality of the embedding 9 | % Default 2. 10 | % opts.perplexity - perplexity is used to determine the 11 | % bandwidth of the Gaussian kernel in the input 12 | % space. Default 30. 13 | % opts.theta - Set to 0 for exact. If non-zero, then will use either 14 | % Barnes Hut or FIt-SNE based on opts.nbody_algo. If Barnes Hut, then 15 | % this determins the accuracy of BH approximation. 16 | % Default 0.5. 17 | % opts.max_iter - Number of iterations of t-SNE to run. 18 | % Default 750. 19 | % opts.nbody_algo - if theta is nonzero, this determins whether to 20 | % use FIt-SNE or Barnes Hut approximation. Default is FIt-SNE. 21 | % set to be 'bh' for Barnes Hut 22 | % opts.knn_algo - use vp-trees (as in bhtsne) or approximate nearest neighbors (default). 23 | % set to be 'vptree' for vp-trees 24 | % opts.early_exag_coeff - coefficient for early exaggeration 25 | % (>1). Default 12. 26 | % opts.stop_early_exag_iter - When to switch off early 27 | % exaggeration. 28 | % Default 250. 29 | % opts.start_late_exag_iter - When to start late exaggeration. 30 | % 'auto' means that late exaggeration is not used, unless 31 | % late_exag_coeff>0. In that case, start_late_exag_iter is 32 | % set to stop_early_exag_iter. Otherwise, set to equal the 33 | % iteration at which late exaggeration should begin. 34 | % Default: 'auto' 35 | % opts.start_late_exag_iter - When to start late 36 | % exaggeration. set to -1 to not use late exaggeration 37 | % Default -1. 38 | % opts.late_exag_coeff - Late exaggeration coefficient. 39 | % Set to -1 to not use late exaggeration. 40 | % Default -1 41 | % opts.learning_rate - Set to desired learning rate or 'auto', 42 | % which sets learning rate to N/early_exag_coeff where 43 | % N is the sample size, or to 200 if N/early_exag_coeff 44 | % < 200. 45 | % Default 'auto' 46 | % opts.max_step_norm - Maximum distance that a point is 47 | % allowed to move on one iteration. Larger steps are clipped 48 | % to this value. This prevents possible instabilities during 49 | % gradient descent. Set to -1 to switch it off. 50 | % Default: 5 51 | % opts.no_momentum_during_exag - Set to 0 to use momentum 52 | % and other optimization tricks. 1 to do plain,vanilla 53 | % gradient descent (useful for testing large exaggeration 54 | % coefficients) 55 | % opts.nterms - If using FIt-SNE, this is the number of 56 | % interpolation points per sub-interval 57 | % opts.intervals_per_integer - See opts.min_num_intervals 58 | % opts.min_num_intervals - Let maxloc = ceil(max(max(X))) 59 | % and minloc = floor(min(min(X))). i.e. the points are in 60 | % a [minloc]^no_dims by [maxloc]^no_dims interval/square. 61 | % The number of intervals in each dimension is either 62 | % opts.min_num_intervals or ceil((maxloc - 63 | % minloc)/opts.intervals_per_integer), whichever is 64 | % larger. opts.min_num_intervals must be an integer >0, 65 | % and opts.intervals_per_integer must be >0. Default: 66 | % opts.min_num_intervals=50, opts.intervals_per_integer = 67 | % 1 68 | % 69 | % opts.sigma - Fixed sigma value to use when perplexity==-1 70 | % Default -1 (None) 71 | % opts.K - Number of nearest neighbours to get when using fixed sigma 72 | % Default -30 (None) 73 | % 74 | % opts.initialization - 'pca', 'random', or N x no_dims array 75 | % to intialize the solution 76 | % Default: 'pca' 77 | % 78 | % opts.load_affinities - can be 'load', 'save', or 'none' (default) 79 | % If 'save', input similarities are saved into a file. 80 | % If 'load', input similarities are loaded from a file and not computed 81 | % 82 | % opts.perplexity_list - if perplexity==0 then perplexity 83 | % combination will be used with values taken from 84 | % perplexity_list. Default: [] 85 | % opts.df - Degree of freedom of t-distribution, must be greater than 0. 86 | % Values smaller than 1 correspond to heavier tails, which can often 87 | % resolve substructure in the embedding. See Kobak et al. (2019) for 88 | % details. Default is 1.0 89 | 90 | 91 | 92 | % Runs the C++ implementation of fast t-SNE using either the IFt-SNE 93 | % implementation or Barnes Hut 94 | 95 | 96 | % Copyright (c) 2014, Laurens van der Maaten (Delft University of Technology) 97 | % All rights reserved. 98 | % 99 | % Redistribution and use in source and binary forms, with or without 100 | % modification, are permitted provided that the following conditions are met: 101 | % 1. Redistributions of source code must retain the above copyright 102 | % notice, this list of conditions and the following disclaimer. 103 | % 2. Redistributions in binary form must reproduce the above copyright 104 | % notice, this list of conditions and the following disclaimer in the 105 | % documentation and/or other materials provided with the distribution. 106 | % 3. All advertising materials mentioning features or use of this software 107 | % must display the following acknowledgement: 108 | % This product includes software developed by the Delft University of Technology. 109 | % 4. Neither the name of the Delft University of Technology nor the names of 110 | % its contributors may be used to endorse or promote products derived from 111 | % this software without specific prior written permission. 112 | % 113 | % THIS SOFTWARE IS PROVIDED BY LAURENS VAN DER MAATEN ''AS IS'' AND ANY EXPRESS 114 | % OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 115 | % OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 116 | % EVENT SHALL LAURENS VAN DER MAATEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 117 | % SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 118 | % PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 119 | % BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 120 | % CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 121 | % IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 122 | % OF SUCH DAMAGE. 123 | 124 | version_number = '1.2.1'; 125 | 126 | % default parameters and flags 127 | p.perplexity = 30; 128 | p.no_dims = 2; 129 | p.theta = .5; 130 | p.stop_early_exag_iter = 250; % stop_lying_iter 131 | p.mom_switch_iter = 250; 132 | p.momentum = .5; 133 | p.final_momentum = .8; 134 | p.learning_rate = 'auto'; 135 | p.max_step_norm = 5; 136 | p.max_iter = 750; 137 | p.early_exag_coeff = 12; 138 | p.start_late_exag_iter = 'auto'; 139 | p.late_exag_coeff = -1; 140 | p.rand_seed = -1; 141 | p.nbody_algo = 2; 142 | p.knn_algo = 1; 143 | p.K = -1; 144 | p.sigma = -30; 145 | p.no_momentum_during_exag = 0; 146 | p.n_trees = 50; 147 | p.perplexity_list = []; 148 | p.nterms = 3; 149 | p.intervals_per_integer = 1; 150 | p.min_num_intervals = 50; 151 | p.nthreads = 0; 152 | p.df = 1; 153 | p.search_k = []; 154 | p.initialization = 'auto'; 155 | p.load_affinities = 0; 156 | 157 | 158 | if nargin == 2 159 | % options provided 160 | 161 | assert(isstruct(opts),'2nd argument must be a structure') 162 | 163 | % copy over user-supplied parameters and options 164 | fn = fieldnames(p); 165 | for i = 1:length(fn) 166 | if isfield(opts,fn{i}) 167 | p.(fn{i}) = opts.(fn{i}); 168 | end 169 | end 170 | 171 | end 172 | 173 | if strcmpi(p.learning_rate,'auto') 174 | p.learning_rate = max(200, size(X,1)/p.early_exag_coeff) 175 | end 176 | 177 | if strcmpi(p.start_late_exag_iter,'auto') 178 | if p.late_exag_coeff > 0 179 | p.start_late_exag_iter = p.stop_early_exag_iter 180 | else 181 | p.start_late_exag_iter = -1 182 | end 183 | end 184 | 185 | if strcmpi(p.initialization,'auto') 186 | if p.rand_seed>0 187 | rng(p.rand_seed) 188 | end 189 | X_c = mean(X ,1); 190 | X_c = bsxfun(@minus,X,X_c); 191 | p.no_dims = 2 192 | [U, S,V ] = svds(X_c, p.no_dims); 193 | PCs = U * S; 194 | p.initialization = 0.0001*(PCs/std(PCs(:,1))) 195 | elseif strcmpi(p.initialization,'random') 196 | p.initialization = NaN; 197 | end 198 | 199 | % parse some optional text labels 200 | if strcmpi(p.nbody_algo,'bh') 201 | p.nbody_algo = 1; 202 | end 203 | 204 | 205 | if strcmpi(p.knn_algo,'vptree') 206 | p.knn_algo = 2; 207 | end 208 | 209 | 210 | if isempty(p.search_k) 211 | if p.perplexity > 0 212 | p.search_k = 3*p.perplexity*p.n_trees; 213 | elseif p.perplexity == 0 214 | p.search_k = 3 * max(p.perplexity_list) * p.n_trees; 215 | else 216 | p.search_k = 3*p.K*p.n_trees; 217 | end 218 | end 219 | 220 | 221 | 222 | if p.load_affinities == 'load' 223 | p.load_affinities = 1; 224 | elseif p.load_affinities == 'save' 225 | p.load_affinities = 2; 226 | else 227 | p.load_affinities = 0; 228 | end 229 | 230 | 231 | X = double(X); 232 | 233 | tsne_path = which('fast_tsne'); 234 | tsne_path = strcat(tsne_path(1:end-11), 'bin') 235 | 236 | % Compile t-SNE C code 237 | if(~exist(fullfile(tsne_path,'./fast_tsne'),'file') && isunix) 238 | system(sprintf('g++ -std=c++11 -O3 src/sptree.cpp src/tsne.cpp src/nbodyfft.cpp -o bin/fast_tsne -pthread -lfftw3 -lm')); 239 | end 240 | 241 | % Compile t-SNE C code on Windows 242 | if(~exist(fullfile(tsne_path,'FItSNE.exe'),'file') && ispc) 243 | system(sprintf('g++ -std=c++11 -O3 src/sptree.cpp src/tsne.cpp src/nbodyfft.cpp -o bin/FItSNE.exe -pthread -lfftw3 -lm')); 244 | end 245 | 246 | % Run the fast diffusion SNE implementation 247 | write_data('data.dat', X, p.no_dims, p.theta, p.perplexity, p.max_iter, ... 248 | p.stop_early_exag_iter, p.K, p.sigma, p.nbody_algo, p.no_momentum_during_exag, p.knn_algo,... 249 | p.early_exag_coeff, p.n_trees, p.search_k, p.start_late_exag_iter, p.late_exag_coeff, p.rand_seed,... 250 | p.nterms, p.intervals_per_integer, p.min_num_intervals, p.initialization, p.load_affinities, ... 251 | p.perplexity_list, p.mom_switch_iter, p.momentum, p.final_momentum, p.learning_rate,p.max_step_norm,p.df); 252 | 253 | disp('Data written'); 254 | tic 255 | %[flag, cmdout] = system(fullfile(tsne_path,'/fast_tsne'), '-echo'); 256 | cmd = sprintf('%s %s data.dat result.dat %d',fullfile(tsne_path,'/fast_tsne'), version_number, p.nthreads); 257 | [flag, cmdout] = system(cmd, '-echo'); 258 | if(flag~=0) 259 | error(cmdout); 260 | end 261 | toc 262 | [mappedX, costs] = read_data('result.dat', p.max_iter); 263 | delete('data.dat'); 264 | delete('result.dat'); 265 | end 266 | 267 | 268 | % Writes the datafile for the fast t-SNE implementation 269 | function write_data(filename, X, no_dims, theta, perplexity, max_iter,... 270 | stop_lying_iter, K, sigma, nbody_algo, no_momentum_during_exag, knn_algo,... 271 | early_exag_coeff, n_trees, search_k, start_late_exag_iter, late_exag_coeff, rand_seed,... 272 | nterms, intervals_per_integer, min_num_intervals, initialization, load_affinities, ... 273 | perplexity_list, mom_switch_iter, momentum, final_momentum, learning_rate,max_step_norm,df) 274 | 275 | [n, d] = size(X); 276 | 277 | h = fopen(filename, 'wb'); 278 | fwrite(h, n, 'integer*4'); 279 | fwrite(h, d, 'integer*4'); 280 | fwrite(h, theta, 'double'); 281 | fwrite(h, perplexity, 'double'); 282 | if perplexity == 0 283 | fwrite(h, length(perplexity_list), 'integer*4'); 284 | fwrite(h, perplexity_list, 'double'); 285 | end 286 | fwrite(h, no_dims, 'integer*4'); 287 | fwrite(h, max_iter, 'integer*4'); 288 | fwrite(h, stop_lying_iter, 'integer*4'); 289 | fwrite(h, mom_switch_iter, 'integer*4'); 290 | fwrite(h, momentum, 'double'); 291 | fwrite(h, final_momentum, 'double'); 292 | fwrite(h, learning_rate, 'double'); 293 | fwrite(h, max_step_norm, 'double'); 294 | fwrite(h, K, 'int'); 295 | fwrite(h, sigma, 'double'); 296 | fwrite(h, nbody_algo, 'int'); 297 | fwrite(h, knn_algo, 'int'); 298 | fwrite(h, early_exag_coeff, 'double'); 299 | fwrite(h, no_momentum_during_exag, 'int'); 300 | fwrite(h, n_trees, 'int'); 301 | fwrite(h, search_k, 'int'); 302 | fwrite(h, start_late_exag_iter, 'int'); 303 | fwrite(h, late_exag_coeff, 'double'); 304 | fwrite(h, nterms, 'int'); 305 | fwrite(h, intervals_per_integer, 'double'); 306 | fwrite(h, min_num_intervals, 'int'); 307 | fwrite(h, X', 'double'); 308 | fwrite(h, rand_seed, 'integer*4'); 309 | fwrite(h, df, 'double'); 310 | fwrite(h, load_affinities, 'integer*4'); 311 | if ~isnan(initialization) 312 | fwrite(h, initialization', 'double'); 313 | end 314 | fclose(h); 315 | end 316 | 317 | 318 | % Reads the result file from the fast t-SNE implementation 319 | function [X, costs] = read_data(file_name, max_iter) 320 | h = fopen(file_name, 'rb'); 321 | n = fread(h, 1, 'integer*4'); 322 | d = fread(h, 1, 'integer*4'); 323 | X = fread(h, n * d, 'double'); 324 | max_iter = fread(h, 1, 'integer*4'); 325 | costs = fread(h, max_iter, 'double'); 326 | X = reshape(X, [d n])'; 327 | fclose(h); 328 | end 329 | -------------------------------------------------------------------------------- /fast_tsne.py: -------------------------------------------------------------------------------- 1 | # This is a really basic function that does not do almost any sanity checks 2 | # 3 | # Usage example: 4 | # import sys; sys.path.append('../FIt-SNE/') 5 | # from fast_tsne import fast_tsne 6 | # import numpy as np 7 | # X = np.random.randn(1000, 50) 8 | # Z = fast_tsne(X) 9 | # 10 | # Written by Dmitry Kobak 11 | 12 | 13 | import os 14 | import subprocess 15 | import struct 16 | import numpy as np 17 | from datetime import datetime 18 | 19 | def fast_tsne( 20 | X, 21 | theta=0.5, 22 | perplexity=30, 23 | map_dims=2, 24 | max_iter=750, 25 | stop_early_exag_iter=250, 26 | K=-1, 27 | sigma=-1, 28 | nbody_algo="FFT", 29 | knn_algo="annoy", 30 | mom_switch_iter=250, 31 | momentum=0.5, 32 | final_momentum=0.8, 33 | learning_rate="auto", 34 | early_exag_coeff=12, 35 | no_momentum_during_exag=False, 36 | n_trees=50, 37 | search_k=None, 38 | start_late_exag_iter="auto", 39 | late_exag_coeff=-1, 40 | nterms=3, 41 | intervals_per_integer=1, 42 | min_num_intervals=50, 43 | seed=-1, 44 | initialization="pca", 45 | load_affinities=None, 46 | perplexity_list=None, 47 | df=1, 48 | return_loss=False, 49 | nthreads=-1, 50 | max_step_norm=5, 51 | ): 52 | """Run t-SNE. This implementation supports exact t-SNE, Barnes-Hut t-SNE 53 | and FFT-accelerated interpolation-based t-SNE (FIt-SNE). This is a Python 54 | wrapper to a C++ executable. 55 | 56 | Parameters 57 | ---------- 58 | X: 2D numpy array 59 | Array of observations (n times p) 60 | perplexity: double 61 | Perplexity is used to determine the bandwidth of the Gaussian kernel 62 | in the input space. Default 30. 63 | theta: double 64 | Set to 0 for exact t-SNE. If non-zero, then the code will use either 65 | Barnes Hut or FIt-SNE based on `nbody_algo`. If Barnes Hut, then theta 66 | determins the accuracy of BH approximation. Default 0.5. 67 | map_dims: int 68 | Number of embedding dimensions. Default 2. FIt-SNE supports only 1 or 2 69 | dimensions. 70 | max_iter: int 71 | Number of gradient descent iterations. Default 750. 72 | nbody_algo: {'Barnes-Hut', 'FFT'} 73 | If theta is nonzero, this determines whether to use FIt-SNE (default) or 74 | Barnes-Hut approximation. 75 | knn_algo: {'vp-tree', 'annoy'} 76 | Use exact nearest neighbours with VP trees (as in BH t-SNE) or 77 | approximate nearest neighbors with Annoy. Default is 'annoy'. 78 | early_exag_coeff: double 79 | Coefficient for early exaggeration. Default 12. 80 | stop_early_exag_iter: int 81 | When to switch off early exaggeration. Default 250. 82 | late_exag_coeff: double 83 | Coefficient for late exaggeration. Set to -1 in order not to use late 84 | exaggeration. Default -1. 85 | start_late_exag_iter: int or 'auto' 86 | When to start late exaggeration. Default 'auto'; it sets 87 | start_late_exag_iter to -1 meaning that late exaggeration is not used, 88 | unless late_exag_coeff>0. In that case start_late_exag_iter is set to 89 | stop_early_exag_iter. 90 | momentum: double 91 | Initial value of momentum. Default 0.5. 92 | final_momentum: double 93 | The value of momentum to use later in the optimisation. Default 0.8. 94 | mom_switch_iter: int 95 | Iteration number to switch from momentum to final_momentum. Default 250. 96 | learning_rate: double or 'auto' 97 | Learning rate. Default 'auto'; it sets learning rate to 98 | N/early_exag_coeff where N is the sample size, or to 200 if 99 | N/early_exag_coeff < 200. 100 | max_step_norm: double or 'none' (default: 5) 101 | Maximum distance that a point is allowed to move on one iteration. 102 | Larger steps are clipped to this value. This prevents possible 103 | instabilities during gradient descent. Set to 'none' to switch it off. 104 | no_mometum_during_exag: boolean 105 | Whether to switch off momentum during the early exaggeration phase (can 106 | be useful for experiments with large exaggeration coefficients). Default 107 | is False. 108 | sigma: boolean 109 | The standard deviation of the Gaussian kernel to be used for all points 110 | instead of choosing it adaptively via perplexity. Set to -1 to use 111 | perplexity. Default is -1. 112 | K: int 113 | The number of nearest neighbours to use when using fixed sigma instead 114 | of perplexity calibration. Set to -1 when perplexity is used. Default 115 | is -1. 116 | nterms: int 117 | If using FIt-SNE, this is the number of interpolation points per 118 | sub-interval 119 | intervals_per_integer: double 120 | See min_num_intervals 121 | min_num_intervals: int 122 | The interpolation grid is chosen on each step of the gradient descent. 123 | If Y is the current embedding, let maxloc = ceiling(max(Y.flatten)) and 124 | minloc = floor(min(Y.flatten)), i.e. the points are contained in a 125 | [minloc, maxloc]^no_dims box. The number of intervals in each 126 | dimension is either min_num_intervals or 127 | ceiling((maxloc-minloc)/intervals_per_integer), whichever is larger. 128 | min_num_intervals must be a positive integer and intervals_per_integer 129 | must be positive real value. Defaults: min_num_intervals=50, 130 | intervals_per_integer = 1. 131 | n_trees: int 132 | When using Annoy, the number of search trees to use. Default is 50. 133 | search_k: int 134 | When using Annoy, the number of nodes to inspect during search. Default 135 | is 3*perplexity*n_trees (or K*n_trees when using fixed sigma). 136 | seed: int 137 | Seed for random initialisation. Use -1 to initialise random number 138 | generator with current time. Default -1. 139 | initialization: 'random', 'pca', or numpy array 140 | N x no_dims array to intialize the solution. Default: 'pca'. 141 | load_affinities: {'load', 'save', None} 142 | If 'save', input similarities (p_ij) are saved into a file. If 'load', 143 | they are loaded from a file and not recomputed. If None, they are not 144 | saved and not loaded. Default is None. 145 | perplexity_list: list 146 | A list of perplexities to used as a perplexity combination. Input 147 | affinities are computed with each perplexity on the list and then 148 | averaged. Default is None. 149 | nthreads: int 150 | Number of threads to use. Default is -1, i.e. use all available threads. 151 | df: double 152 | Controls the degree of freedom of t-distribution. Must be positive. The 153 | actual degree of freedom is 2*df-1. The standard t-SNE choice of 1 154 | degree of freedom corresponds to df=1. Large df approximates Gaussian 155 | kernel. df<1 corresponds to heavier tails, which can often resolve 156 | substructure in the embedding. See Kobak et al. (2019) for details. 157 | Default is 1.0. 158 | return_loss: boolean 159 | If True, the function returns the loss values computed during 160 | optimisation together with the final embedding. If False, only the 161 | embedding is returned. Default is False. 162 | 163 | Returns 164 | ------- 165 | Y: numpy array 166 | The embedding. 167 | loss: numpy array 168 | Loss values computed during optimisation. Only returned if return_loss 169 | is True. 170 | """ 171 | 172 | version_number = "1.2.1" 173 | 174 | # X should be a numpy array of 64-bit doubles 175 | X = np.array(X).astype(float) 176 | 177 | if learning_rate == "auto": 178 | learning_rate = np.max((200, X.shape[0] / early_exag_coeff)) 179 | 180 | if start_late_exag_iter == "auto": 181 | if late_exag_coeff > 0: 182 | start_late_exag_iter = stop_early_exag_iter 183 | else: 184 | start_late_exag_iter = -1 185 | 186 | if isinstance(initialization, str) and initialization == "pca": 187 | from sklearn.decomposition import PCA 188 | 189 | solver = "arpack" if X.shape[1] > map_dims else "auto" 190 | pca = PCA( 191 | n_components=map_dims, 192 | svd_solver=solver, 193 | random_state=seed if seed != -1 else None, 194 | ) 195 | initialization = pca.fit_transform(X) 196 | initialization /= np.std(initialization[:, 0]) 197 | initialization *= 0.0001 198 | 199 | if perplexity_list is not None: 200 | perplexity = 0 # C++ requires perplexity=0 in order to use perplexity_list 201 | 202 | if sigma > 0 and K > 0: 203 | perplexity = -1 # C++ requires perplexity=-1 in order to use sigma 204 | 205 | if search_k is None: 206 | if perplexity > 0: 207 | search_k = 3 * perplexity * n_trees 208 | elif perplexity == 0: 209 | search_k = 3 * np.max(perplexity_list) * n_trees 210 | else: 211 | search_k = K * n_trees 212 | 213 | # Not much of a speed up, at least on some machines, so I'm removing it. 214 | # 215 | # if nbody_algo == 'auto': 216 | # if X.shape[0] < 8000: 217 | # nbody_algo = 'Barnes-Hut' 218 | # else: 219 | # nbody_algo = 'FFT' 220 | 221 | if nbody_algo == "Barnes-Hut": 222 | nbody_algo = 1 223 | elif nbody_algo == "FFT": 224 | nbody_algo = 2 225 | else: 226 | raise ValueError("nbody_algo should be 'Barnes-Hut' or 'FFT'") 227 | 228 | if knn_algo == "vp-tree": 229 | knn_algo = 2 230 | elif knn_algo == "annoy": 231 | knn_algo = 1 232 | else: 233 | raise ValueError("knn_algo should be 'vp-tree' or 'annoy'") 234 | 235 | if load_affinities == "load": 236 | load_affinities = 1 237 | elif load_affinities == "save": 238 | load_affinities = 2 239 | else: 240 | load_affinities = 0 241 | 242 | if nthreads == -1: 243 | nthreads = 0 244 | 245 | if max_step_norm == "none": 246 | max_step_norm = -1 247 | 248 | if no_momentum_during_exag: 249 | no_momentum_during_exag = 1 250 | else: 251 | no_momentum_during_exag = 0 252 | 253 | # create unique i/o-filenames 254 | timestamp = str(datetime.now()) + '-' + str(np.random.randint(0,1000000000)) 255 | infile = 'data_%s.dat' % timestamp 256 | outfile = 'result_%s.dat' % timestamp 257 | 258 | # write data file 259 | with open(os.getcwd() + '/' + infile, 'wb') as f: 260 | n, d = X.shape 261 | f.write(struct.pack("=i", n)) 262 | f.write(struct.pack("=i", d)) 263 | f.write(struct.pack("=d", theta)) 264 | f.write(struct.pack("=d", perplexity)) 265 | if perplexity == 0: 266 | f.write(struct.pack("=i", len(perplexity_list))) 267 | for perpl in perplexity_list: 268 | f.write(struct.pack("=d", perpl)) 269 | f.write(struct.pack("=i", map_dims)) 270 | f.write(struct.pack("=i", max_iter)) 271 | f.write(struct.pack("=i", stop_early_exag_iter)) 272 | f.write(struct.pack("=i", mom_switch_iter)) 273 | f.write(struct.pack("=d", momentum)) 274 | f.write(struct.pack("=d", final_momentum)) 275 | f.write(struct.pack("=d", learning_rate)) 276 | f.write(struct.pack("=d", max_step_norm)) 277 | f.write(struct.pack("=i", K)) 278 | f.write(struct.pack("=d", sigma)) 279 | f.write(struct.pack("=i", nbody_algo)) 280 | f.write(struct.pack("=i", knn_algo)) 281 | f.write(struct.pack("=d", early_exag_coeff)) 282 | f.write(struct.pack("=i", no_momentum_during_exag)) 283 | f.write(struct.pack("=i", n_trees)) 284 | f.write(struct.pack("=i", search_k)) 285 | f.write(struct.pack("=i", start_late_exag_iter)) 286 | f.write(struct.pack("=d", late_exag_coeff)) 287 | f.write(struct.pack("=i", nterms)) 288 | f.write(struct.pack("=d", intervals_per_integer)) 289 | f.write(struct.pack("=i", min_num_intervals)) 290 | f.write(X.tobytes()) 291 | f.write(struct.pack("=i", seed)) 292 | f.write(struct.pack("=d", df)) 293 | f.write(struct.pack("=i", load_affinities)) 294 | 295 | if not isinstance(initialization, str) or initialization != "random": 296 | initialization = np.array(initialization).astype(float) 297 | f.write(initialization.tobytes()) 298 | 299 | # run t-sne 300 | subprocess.call( 301 | [ 302 | os.path.dirname(os.path.realpath(__file__)) + "/bin/fast_tsne", 303 | version_number, 304 | infile, 305 | outfile, 306 | "{}".format(nthreads), 307 | ] 308 | ) 309 | 310 | # read data file 311 | with open(os.getcwd() + '/' + outfile, 'rb') as f: 312 | (n,) = struct.unpack("=i", f.read(4)) 313 | (md,) = struct.unpack("=i", f.read(4)) 314 | sz = struct.calcsize("=d") 315 | buf = f.read(sz * n * md) 316 | x_tsne = [ 317 | struct.unpack_from("=d", buf, sz * offset) for offset in range(n * md) 318 | ] 319 | x_tsne = np.array(x_tsne).reshape((n, md)) 320 | (_,) = struct.unpack("=i", f.read(4)) 321 | buf = f.read(sz * max_iter) 322 | loss = [ 323 | struct.unpack_from("=d", buf, sz * offset) for offset in range(max_iter) 324 | ] 325 | loss = np.array(loss).squeeze() 326 | if loss.size == 1: 327 | loss = loss[np.newaxis] 328 | loss[np.arange(1, max_iter + 1) % 50 > 0] = np.nan 329 | 330 | # remove i/o-files 331 | os.remove(os.getcwd() + '/' + infile) 332 | os.remove(os.getcwd() + '/' + outfile) 333 | 334 | if return_loss: 335 | return (x_tsne, loss) 336 | else: 337 | return x_tsne 338 | 339 | -------------------------------------------------------------------------------- /src/kissrandom.h: -------------------------------------------------------------------------------- 1 | #ifndef KISSRANDOM_H 2 | #define KISSRANDOM_H 3 | 4 | #if defined(_MSC_VER) && _MSC_VER == 1500 5 | typedef unsigned __int32 uint32_t; 6 | typedef unsigned __int64 uint64_t; 7 | #else 8 | #include 9 | #endif 10 | 11 | // KISS = "keep it simple, stupid", but high quality random number generator 12 | // http://www0.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf -> "Use a good RNG and build it into your code" 13 | // http://mathforum.org/kb/message.jspa?messageID=6627731 14 | // https://de.wikipedia.org/wiki/KISS_(Zufallszahlengenerator) 15 | 16 | // 32 bit KISS 17 | struct Kiss32Random { 18 | uint32_t x; 19 | uint32_t y; 20 | uint32_t z; 21 | uint32_t c; 22 | 23 | // seed must be != 0 24 | Kiss32Random(uint32_t seed = 123456789) { 25 | x = seed; 26 | y = 362436000; 27 | z = 521288629; 28 | c = 7654321; 29 | } 30 | 31 | uint32_t kiss() { 32 | // Linear congruence generator 33 | x = 69069 * x + 12345; 34 | 35 | // Xor shift 36 | y ^= y << 13; 37 | y ^= y >> 17; 38 | y ^= y << 5; 39 | 40 | // Multiply-with-carry 41 | uint64_t t = 698769069ULL * z + c; 42 | c = t >> 32; 43 | z = (uint32_t) t; 44 | 45 | return x + y + z; 46 | } 47 | inline int flip() { 48 | // Draw random 0 or 1 49 | return kiss() & 1; 50 | } 51 | inline size_t index(size_t n) { 52 | // Draw random integer between 0 and n-1 where n is at most the number of data points you have 53 | return kiss() % n; 54 | } 55 | inline void set_seed(uint32_t seed) { 56 | x = seed; 57 | } 58 | }; 59 | 60 | // 64 bit KISS. Use this if you have more than about 2^24 data points ("big data" ;) ) 61 | struct Kiss64Random { 62 | uint64_t x; 63 | uint64_t y; 64 | uint64_t z; 65 | uint64_t c; 66 | 67 | // seed must be != 0 68 | Kiss64Random(uint64_t seed = 1234567890987654321ULL) { 69 | x = seed; 70 | y = 362436362436362436ULL; 71 | z = 1066149217761810ULL; 72 | c = 123456123456123456ULL; 73 | } 74 | 75 | uint64_t kiss() { 76 | // Linear congruence generator 77 | z = 6906969069LL*z+1234567; 78 | 79 | // Xor shift 80 | y ^= (y<<13); 81 | y ^= (y>>17); 82 | y ^= (y<<43); 83 | 84 | // Multiply-with-carry (uint128_t t = (2^58 + 1) * x + c; c = t >> 64; x = (uint64_t) t) 85 | uint64_t t = (x<<58)+c; 86 | c = (x>>6); 87 | x += t; 88 | c += (x *fft_kernel_tilde, double df ) { 12 | /* 13 | * Set up the boxes 14 | */ 15 | int n_total_boxes = n_boxes * n_boxes; 16 | double box_width = (x_max - x_min) / (double) n_boxes; 17 | 18 | // Left and right bounds of each box, first the lower bounds in the x direction, then in the y direction 19 | for (int i = 0; i < n_boxes; i++) { 20 | for (int j = 0; j < n_boxes; j++) { 21 | box_lower_bounds[i * n_boxes + j] = j * box_width + x_min; 22 | box_upper_bounds[i * n_boxes + j] = (j + 1) * box_width + x_min; 23 | 24 | box_lower_bounds[n_total_boxes + i * n_boxes + j] = i * box_width + y_min; 25 | box_upper_bounds[n_total_boxes + i * n_boxes + j] = (i + 1) * box_width + y_min; 26 | } 27 | } 28 | 29 | // Coordinates of each (equispaced) interpolation node for a single box 30 | double h = 1 / (double) n_interpolation_points; 31 | y_tilde_spacings[0] = h / 2; 32 | for (int i = 1; i < n_interpolation_points; i++) { 33 | y_tilde_spacings[i] = y_tilde_spacings[i - 1] + h; 34 | } 35 | 36 | // Coordinates of all the equispaced interpolation points 37 | int n_interpolation_points_1d = n_interpolation_points * n_boxes; 38 | int n_fft_coeffs = 2 * n_interpolation_points_1d; 39 | 40 | h = h * box_width; 41 | x_tilde[0] = x_min + h / 2; 42 | y_tilde[0] = y_min + h / 2; 43 | for (int i = 1; i < n_interpolation_points_1d; i++) { 44 | x_tilde[i] = x_tilde[i - 1] + h; 45 | y_tilde[i] = y_tilde[i - 1] + h; 46 | } 47 | 48 | /* 49 | * Evaluate the kernel at the interpolation nodes and form the embedded generating kernel vector for a circulant 50 | * matrix 51 | */ 52 | auto *kernel_tilde = new double[n_fft_coeffs * n_fft_coeffs](); 53 | for (int i = 0; i < n_interpolation_points_1d; i++) { 54 | for (int j = 0; j < n_interpolation_points_1d; j++) { 55 | double tmp = kernel(y_tilde[0], x_tilde[0], y_tilde[i], x_tilde[j],df ); 56 | kernel_tilde[(n_interpolation_points_1d + i) * n_fft_coeffs + (n_interpolation_points_1d + j)] = tmp; 57 | kernel_tilde[(n_interpolation_points_1d - i) * n_fft_coeffs + (n_interpolation_points_1d + j)] = tmp; 58 | kernel_tilde[(n_interpolation_points_1d + i) * n_fft_coeffs + (n_interpolation_points_1d - j)] = tmp; 59 | kernel_tilde[(n_interpolation_points_1d - i) * n_fft_coeffs + (n_interpolation_points_1d - j)] = tmp; 60 | } 61 | } 62 | 63 | // Precompute the FFT of the kernel generating matrix 64 | fftw_plan p = fftw_plan_dft_r2c_2d(n_fft_coeffs, n_fft_coeffs, kernel_tilde, 65 | reinterpret_cast(fft_kernel_tilde), FFTW_ESTIMATE); 66 | fftw_execute(p); 67 | 68 | fftw_destroy_plan(p); 69 | delete[] kernel_tilde; 70 | } 71 | 72 | 73 | void n_body_fft_2d(int N, int n_terms, double *xs, double *ys, double *chargesQij, int n_boxes, 74 | int n_interpolation_points, double *box_lower_bounds, double *box_upper_bounds, 75 | double *y_tilde_spacings, complex *fft_kernel_tilde, double *potentialQij, unsigned int nthreads) { 76 | int n_total_boxes = n_boxes * n_boxes; 77 | int total_interpolation_points = n_total_boxes * n_interpolation_points * n_interpolation_points; 78 | 79 | double coord_min = box_lower_bounds[0]; 80 | double box_width = box_upper_bounds[0] - box_lower_bounds[0]; 81 | 82 | auto *point_box_idx = new int[N]; 83 | 84 | // Determine which box each point belongs to 85 | for (int i = 0; i < N; i++) { 86 | auto x_idx = static_cast((xs[i] - coord_min) / box_width); 87 | auto y_idx = static_cast((ys[i] - coord_min) / box_width); 88 | // TODO: Figure out how on earth x_idx can be less than zero... 89 | // It's probably something to do with the fact that we use the single lowest coord for both dims? Probably not 90 | // this, more likely negative 0 if rounding errors 91 | if (x_idx >= n_boxes) { 92 | x_idx = n_boxes - 1; 93 | } else if (x_idx < 0) { 94 | x_idx = 0; 95 | } 96 | 97 | if (y_idx >= n_boxes) { 98 | y_idx = n_boxes - 1; 99 | } else if (y_idx < 0) { 100 | y_idx = 0; 101 | } 102 | point_box_idx[i] = y_idx * n_boxes + x_idx; 103 | } 104 | 105 | // Compute the relative position of each point in its box in the interval [0, 1] 106 | auto *x_in_box = new double[N]; 107 | auto *y_in_box = new double[N]; 108 | for (int i = 0; i < N; i++) { 109 | int box_idx = point_box_idx[i]; 110 | double x_min = box_lower_bounds[box_idx]; 111 | double y_min = box_lower_bounds[n_total_boxes + box_idx]; 112 | x_in_box[i] = (xs[i] - x_min) / box_width; 113 | y_in_box[i] = (ys[i] - y_min) / box_width; 114 | } 115 | 116 | INITIALIZE_TIME 117 | START_TIME 118 | 119 | /* 120 | * Step 1: Interpolate kernel using Lagrange polynomials and compute the w coefficients 121 | */ 122 | // Compute the interpolated values at each real point with each Lagrange polynomial in the `x` direction 123 | auto *x_interpolated_values = new double[N * n_interpolation_points]; 124 | interpolate(n_interpolation_points, N, x_in_box, y_tilde_spacings, x_interpolated_values); 125 | // Compute the interpolated values at each real point with each Lagrange polynomial in the `y` direction 126 | auto *y_interpolated_values = new double[N * n_interpolation_points]; 127 | interpolate(n_interpolation_points, N, y_in_box, y_tilde_spacings, y_interpolated_values); 128 | 129 | auto *w_coefficients = new double[total_interpolation_points * n_terms](); 130 | for (int i = 0; i < N; i++) { 131 | int box_idx = point_box_idx[i]; 132 | int box_j = box_idx / n_boxes; 133 | int box_i = box_idx % n_boxes; 134 | for (int interp_i = 0; interp_i < n_interpolation_points; interp_i++) { 135 | for (int interp_j = 0; interp_j < n_interpolation_points; interp_j++) { 136 | // Compute the index of the point in the interpolation grid of points 137 | int idx = (box_i * n_interpolation_points + interp_i) * (n_boxes * n_interpolation_points) + 138 | (box_j * n_interpolation_points) + interp_j; 139 | for (int d = 0; d < n_terms; d++) { 140 | w_coefficients[idx * n_terms + d] += 141 | y_interpolated_values[interp_j * N + i] * 142 | x_interpolated_values[interp_i * N + i] * 143 | chargesQij[i * n_terms + d]; 144 | } 145 | } 146 | } 147 | } 148 | 149 | END_TIME("Step 1"); 150 | START_TIME; 151 | /* 152 | * Step 2: Compute the values v_{m, n} at the equispaced nodes, multiply the kernel matrix with the coefficients w 153 | */ 154 | auto *y_tilde_values = new double[total_interpolation_points * n_terms](); 155 | int n_fft_coeffs_half = n_interpolation_points * n_boxes; 156 | int n_fft_coeffs = 2 * n_interpolation_points * n_boxes; 157 | auto *mpol_sort = new double[total_interpolation_points]; 158 | 159 | // FFT of fft_input 160 | auto *fft_input = new double[n_fft_coeffs * n_fft_coeffs](); 161 | auto *fft_w_coefficients = new complex[n_fft_coeffs * (n_fft_coeffs / 2 + 1)]; 162 | auto *fft_output = new double[n_fft_coeffs * n_fft_coeffs](); 163 | 164 | fftw_plan plan_dft, plan_idft; 165 | plan_dft = fftw_plan_dft_r2c_2d(n_fft_coeffs, n_fft_coeffs, fft_input, 166 | reinterpret_cast(fft_w_coefficients), FFTW_ESTIMATE); 167 | plan_idft = fftw_plan_dft_c2r_2d(n_fft_coeffs, n_fft_coeffs, reinterpret_cast(fft_w_coefficients), 168 | fft_output, FFTW_ESTIMATE); 169 | 170 | for (int d = 0; d < n_terms; d++) { 171 | for (int i = 0; i < total_interpolation_points; i++) { 172 | mpol_sort[i] = w_coefficients[i * n_terms + d]; 173 | } 174 | 175 | for (int i = 0; i < n_fft_coeffs_half; i++) { 176 | for (int j = 0; j < n_fft_coeffs_half; j++) { 177 | fft_input[i * n_fft_coeffs + j] = mpol_sort[i * n_fft_coeffs_half + j]; 178 | } 179 | } 180 | 181 | fftw_execute(plan_dft); 182 | 183 | // Take the Hadamard product of two complex vectors 184 | for (int i = 0; i < n_fft_coeffs * (n_fft_coeffs / 2 + 1); i++) { 185 | double x_ = fft_w_coefficients[i].real(); 186 | double y_ = fft_w_coefficients[i].imag(); 187 | double u_ = fft_kernel_tilde[i].real(); 188 | double v_ = fft_kernel_tilde[i].imag(); 189 | fft_w_coefficients[i].real(x_ * u_ - y_ * v_); 190 | fft_w_coefficients[i].imag(x_ * v_ + y_ * u_); 191 | } 192 | 193 | // Invert the computed values at the interpolated nodes 194 | fftw_execute(plan_idft); 195 | for (int i = 0; i < n_fft_coeffs_half; i++) { 196 | for (int j = 0; j < n_fft_coeffs_half; j++) { 197 | int row = n_fft_coeffs_half + i; 198 | int col = n_fft_coeffs_half + j; 199 | 200 | // FFTW doesn't perform IDFT normalization, so we have to do it ourselves. This is done by dividing 201 | // the result with the number of points in the input 202 | mpol_sort[i * n_fft_coeffs_half + j] = fft_output[row * n_fft_coeffs + col] / 203 | (double) (n_fft_coeffs * n_fft_coeffs); 204 | } 205 | } 206 | for (int i = 0; i < n_fft_coeffs_half * n_fft_coeffs_half; i++) { 207 | y_tilde_values[i * n_terms + d] = mpol_sort[i]; 208 | } 209 | } 210 | 211 | fftw_destroy_plan(plan_dft); 212 | fftw_destroy_plan(plan_idft); 213 | delete[] fft_w_coefficients; 214 | delete[] fft_input; 215 | delete[] fft_output; 216 | delete[] mpol_sort; 217 | END_TIME("FFT"); 218 | START_TIME 219 | /* 220 | * Step 3: Compute the potentials \tilde{\phi} 221 | */ 222 | PARALLEL_FOR(nthreads,N, { 223 | int box_idx = point_box_idx[loop_i]; 224 | int box_i = box_idx % n_boxes; 225 | int box_j = box_idx / n_boxes; 226 | for (int interp_i = 0; interp_i < n_interpolation_points; interp_i++) { 227 | for (int interp_j = 0; interp_j < n_interpolation_points; interp_j++) { 228 | for (int d = 0; d < n_terms; d++) { 229 | // Compute the index of the point in the interpolation grid of points 230 | int idx = (box_i * n_interpolation_points + interp_i) * (n_boxes * n_interpolation_points) + 231 | (box_j * n_interpolation_points) + interp_j; 232 | potentialQij[loop_i * n_terms + d] += 233 | x_interpolated_values[interp_i * N + loop_i] * 234 | y_interpolated_values[interp_j * N + loop_i] * 235 | y_tilde_values[idx * n_terms + d]; 236 | } 237 | } 238 | } 239 | }); 240 | END_TIME("Step 3"); 241 | delete[] point_box_idx; 242 | delete[] x_interpolated_values; 243 | delete[] y_interpolated_values; 244 | delete[] w_coefficients; 245 | delete[] y_tilde_values; 246 | delete[] x_in_box; 247 | delete[] y_in_box; 248 | } 249 | 250 | 251 | void precompute(double y_min, double y_max, int n_boxes, int n_interpolation_points, kernel_type kernel, 252 | double *box_lower_bounds, double *box_upper_bounds, double *y_tilde_spacing, double *y_tilde, 253 | complex *fft_kernel_vector, double df) { 254 | /* 255 | * Set up the boxes 256 | */ 257 | double box_width = (y_max - y_min) / (double) n_boxes; 258 | // Compute the left and right bounds of each box 259 | for (int box_idx = 0; box_idx < n_boxes; box_idx++) { 260 | box_lower_bounds[box_idx] = box_idx * box_width + y_min; 261 | box_upper_bounds[box_idx] = (box_idx + 1) * box_width + y_min; 262 | } 263 | 264 | int total_interpolation_points = n_interpolation_points * n_boxes; 265 | // Coordinates of each equispaced interpolation point for a single box. This equally spaces them between [0, 1] 266 | // with equal space between the points and half that space between the boundary point and the closest boundary point 267 | // e.g. [0.1, 0.3, 0.5, 0.7, 0.9] with spacings [0.1, 0.2, 0.2, 0.2, 0.2, 0.1], respectively. This ensures that the 268 | // nodes will still be equispaced across box boundaries 269 | double h = 1 / (double) n_interpolation_points; 270 | y_tilde_spacing[0] = h / 2; 271 | for (int i = 1; i < n_interpolation_points; i++) { 272 | y_tilde_spacing[i] = y_tilde_spacing[i - 1] + h; 273 | } 274 | 275 | // Coordinates of all the equispaced interpolation points 276 | h = h * box_width; 277 | y_tilde[0] = y_min + h / 2; 278 | for (int i = 1; i < total_interpolation_points; i++) { 279 | y_tilde[i] = y_tilde[i - 1] + h; 280 | } 281 | 282 | /* 283 | * Evaluate the kernel at the interpolation nodes and form the embedded generating kernel vector for a circulant 284 | * matrix 285 | */ 286 | auto *kernel_vector = new complex[2 * total_interpolation_points](); 287 | // Compute the generating vector x between points K(y_i, y_j) where i = 0, j = 0:N-1 288 | // [0 0 0 0 0 5 4 3 2 1] for linear kernel 289 | // This evaluates the Cauchy kernel centered on y_tilde[0] to all the other points 290 | for (int i = 0; i < total_interpolation_points; i++) { 291 | kernel_vector[total_interpolation_points + i].real(kernel(y_tilde[0], y_tilde[i], df)); 292 | } 293 | // This part symmetrizes the vector, this embeds the Toeplitz generating vector into the circulant generating vector 294 | // but also has the nice property of symmetrizing the Cauchy kernel, which is probably planned 295 | // [0 1 2 3 4 5 4 3 2 1] for linear kernel 296 | for (int i = 1; i < total_interpolation_points; i++) { 297 | kernel_vector[i].real(kernel_vector[2 * total_interpolation_points - i].real()); 298 | } 299 | 300 | // Precompute the FFT of the kernel generating vector 301 | fftw_plan p = fftw_plan_dft_1d(2 * total_interpolation_points, reinterpret_cast(kernel_vector), 302 | reinterpret_cast(fft_kernel_vector), FFTW_FORWARD, FFTW_ESTIMATE); 303 | fftw_execute(p); 304 | fftw_destroy_plan(p); 305 | 306 | delete[] kernel_vector; 307 | } 308 | 309 | 310 | void interpolate(int n_interpolation_points, int N, const double *y_in_box, const double *y_tilde_spacings, 311 | double *interpolated_values) { 312 | // The denominators are the same across the interpolants, so we only need to compute them once 313 | auto *denominator = new double[n_interpolation_points]; 314 | for (int i = 0; i < n_interpolation_points; i++) { 315 | denominator[i] = 1; 316 | for (int j = 0; j < n_interpolation_points; j++) { 317 | if (i != j) { 318 | denominator[i] *= y_tilde_spacings[i] - y_tilde_spacings[j]; 319 | } 320 | } 321 | } 322 | // Compute the numerators and the interpolant value 323 | for (int i = 0; i < N; i++) { 324 | for (int j = 0; j < n_interpolation_points; j++) { 325 | interpolated_values[j * N + i] = 1; 326 | for (int k = 0; k < n_interpolation_points; k++) { 327 | if (j != k) { 328 | interpolated_values[j * N + i] *= y_in_box[i] - y_tilde_spacings[k]; 329 | } 330 | } 331 | interpolated_values[j * N + i] /= denominator[j]; 332 | } 333 | } 334 | 335 | delete[] denominator; 336 | } 337 | 338 | 339 | void nbodyfft(int N, int n_terms, double *Y, double *chargesQij, int n_boxes, int n_interpolation_points, 340 | double *box_lower_bounds, double *box_upper_bounds, double *y_tilde_spacings, double *y_tilde, 341 | complex *fft_kernel_vector, double *potentialsQij) { 342 | int total_interpolation_points = n_interpolation_points * n_boxes; 343 | 344 | double coord_min = box_lower_bounds[0]; 345 | double box_width = box_upper_bounds[0] - box_lower_bounds[0]; 346 | 347 | // Determine which box each point belongs to 348 | auto *point_box_idx = new int[N]; 349 | for (int i = 0; i < N; i++) { 350 | auto box_idx = static_cast((Y[i] - coord_min) / box_width); 351 | // The right most point maps directly into `n_boxes`, while it should belong to the last box 352 | if (box_idx >= n_boxes) { 353 | box_idx = n_boxes - 1; 354 | } 355 | point_box_idx[i] = box_idx; 356 | } 357 | 358 | // Compute the relative position of each point in its box in the interval [0, 1] 359 | auto *y_in_box = new double[N]; 360 | for (int i = 0; i < N; i++) { 361 | int box_idx = point_box_idx[i]; 362 | double box_min = box_lower_bounds[box_idx]; 363 | y_in_box[i] = (Y[i] - box_min) / box_width; 364 | } 365 | 366 | /* 367 | * Step 1: Interpolate kernel using Lagrange polynomials and compute the w coefficients 368 | */ 369 | // Compute the interpolated values at each real point with each Lagrange polynomial 370 | auto *interpolated_values = new double[n_interpolation_points * N]; 371 | interpolate(n_interpolation_points, N, y_in_box, y_tilde_spacings, interpolated_values); 372 | 373 | auto *w_coefficients = new double[total_interpolation_points * n_terms](); 374 | for (int i = 0; i < N; i++) { 375 | int box_idx = point_box_idx[i] * n_interpolation_points; 376 | for (int interp_idx = 0; interp_idx < n_interpolation_points; interp_idx++) { 377 | for (int d = 0; d < n_terms; d++) { 378 | w_coefficients[(box_idx + interp_idx) * n_terms + d] += 379 | interpolated_values[interp_idx * N + i] * chargesQij[i * n_terms + d]; 380 | } 381 | } 382 | } 383 | 384 | // `embedded_w_coefficients` is just a vector of zeros prepended to `w_coefficients`, this (probably) matches the 385 | // dimensions of the kernel matrix K and since we embedded the generating vector by prepending values, we have to do 386 | // the same here 387 | auto *embedded_w_coefficients = new double[2 * total_interpolation_points * n_terms](); 388 | for (int i = 0; i < total_interpolation_points; i++) { 389 | for (int d = 0; d < n_terms; d++) { 390 | embedded_w_coefficients[(total_interpolation_points + i) * n_terms + d] = w_coefficients[i * n_terms + d]; 391 | } 392 | } 393 | 394 | /* 395 | * Step 2: Compute the values v_{m, n} at the equispaced nodes, multiply the kernel matrix with the coefficients w 396 | */ 397 | auto *fft_w_coefficients = new complex[2 * total_interpolation_points]; 398 | auto *y_tilde_values = new double[total_interpolation_points * n_terms](); 399 | 400 | fftw_plan plan_dft, plan_idft; 401 | plan_dft = fftw_plan_dft_1d(2 * total_interpolation_points, reinterpret_cast(fft_w_coefficients), 402 | reinterpret_cast(fft_w_coefficients), FFTW_FORWARD, FFTW_ESTIMATE); 403 | plan_idft = fftw_plan_dft_1d(2 * total_interpolation_points, reinterpret_cast(fft_w_coefficients), 404 | reinterpret_cast(fft_w_coefficients), FFTW_BACKWARD, FFTW_ESTIMATE); 405 | 406 | for (int d = 0; d < n_terms; d++) { 407 | for (int i = 0; i < 2 * total_interpolation_points; i++) { 408 | fft_w_coefficients[i].real(embedded_w_coefficients[i * n_terms + d]); 409 | } 410 | fftw_execute(plan_dft); 411 | 412 | // Take the Hadamard product of two complex vectors 413 | for (int i = 0; i < 2 * total_interpolation_points; i++) { 414 | double x_ = fft_w_coefficients[i].real(); 415 | double y_ = fft_w_coefficients[i].imag(); 416 | double u_ = fft_kernel_vector[i].real(); 417 | double v_ = fft_kernel_vector[i].imag(); 418 | fft_w_coefficients[i].real(x_ * u_ - y_ * v_); 419 | fft_w_coefficients[i].imag(x_ * v_ + y_ * u_); 420 | } 421 | 422 | // Invert the computed values at the interpolated nodes, unfortunate naming but it's better to do IDFT inplace 423 | fftw_execute(plan_idft); 424 | 425 | for (int i = 0; i < total_interpolation_points; i++) { 426 | // FFTW doesn't perform IDFT normalization, so we have to do it ourselves. This is done by multiplying the 427 | // result with the number of points in the input 428 | y_tilde_values[i * n_terms + d] = fft_w_coefficients[i].real() / (total_interpolation_points * 2.0); 429 | } 430 | } 431 | 432 | fftw_destroy_plan(plan_dft); 433 | fftw_destroy_plan(plan_idft); 434 | delete[] fft_w_coefficients; 435 | 436 | /* 437 | * Step 3: Compute the potentials \tilde{\phi} 438 | */ 439 | for (int i = 0; i < N; i++) { 440 | int box_idx = point_box_idx[i] * n_interpolation_points; 441 | for (int j = 0; j < n_interpolation_points; j++) { 442 | for (int d = 0; d < n_terms; d++) { 443 | potentialsQij[i * n_terms + d] += 444 | interpolated_values[j * N + i] * y_tilde_values[(box_idx + j) * n_terms + d]; 445 | } 446 | } 447 | } 448 | 449 | delete[] point_box_idx; 450 | delete[] y_in_box; 451 | delete[] interpolated_values; 452 | delete[] w_coefficients; 453 | delete[] y_tilde_values; 454 | delete[] embedded_w_coefficients; 455 | } 456 | -------------------------------------------------------------------------------- /src/nbodyfft.h: -------------------------------------------------------------------------------- 1 | #ifndef NBODYFFT_H 2 | #define NBODYFFT_H 3 | 4 | #ifdef _WIN32 5 | #include "winlibs/fftw3.h" 6 | #else 7 | #include 8 | #endif 9 | #include 10 | 11 | using namespace std; 12 | 13 | typedef double (*kernel_type)(double, double, double); 14 | 15 | typedef double (*kernel_type_2d)(double, double, double, double, double); 16 | 17 | void precompute_2d(double x_max, double x_min, double y_max, double y_min, int n_boxes, int n_interpolation_points, 18 | kernel_type_2d kernel, double *box_lower_bounds, double *box_upper_bounds, double *y_tilde_spacings, 19 | double *y_tilde, double *x_tilde, complex *fft_kernel_tilde, double df); 20 | 21 | void n_body_fft_2d(int N, int n_terms, double *xs, double *ys, double *chargesQij, int n_boxes, 22 | int n_interpolation_points, double *box_lower_bounds, double *box_upper_bounds, 23 | double *y_tilde_spacings, complex *fft_kernel_tilde, double *potentialQij, unsigned int nthreads); 24 | 25 | void precompute(double y_min, double y_max, int n_boxes, int n_interpolation_points, kernel_type kernel, 26 | double *box_lower_bounds, double *box_upper_bounds, double *y_tilde_spacing, double *y_tilde, 27 | complex *fft_kernel_vector, double df); 28 | 29 | void nbodyfft(int N, int n_terms, double *Y, double *chargesQij, int n_boxes, int n_interpolation_points, 30 | double *box_lower_bounds, double *box_upper_bounds, double *y_tilde_spacings, double *y_tilde, 31 | complex *fft_kernel_vector, double *potentialsQij); 32 | 33 | void interpolate(int n_interpolation_points, int N, const double *y_in_box, const double *y_tilde_spacings, 34 | double *interpolated_values); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/parallel_for.h: -------------------------------------------------------------------------------- 1 | #ifndef PARALLEL_FOR_H 2 | #define PARALLEL_FOR_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #if defined(_OPENMP) 8 | #pragma message "Using OpenMP threading." 9 | #define PARALLEL_FOR(nthreads,LOOP_END,O) { \ 10 | if (nthreads >1 ) { \ 11 | _Pragma("omp parallel num_threads(nthreads)") \ 12 | { \ 13 | _Pragma("omp for") \ 14 | for (int loop_i=0; loop_i1 ) { \ 28 | std::vector threads(nthreads); \ 29 | for (int t = 0; t < nthreads; t++) { \ 30 | threads[t] = std::thread(std::bind( \ 31 | [&](const int bi, const int ei, const int t) { \ 32 | for(int loop_i = bi;loop_i 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /src/progress_bar/ProgressBar.hpp: -------------------------------------------------------------------------------- 1 | #ifndef PROGRESSBAR_PROGRESSBAR_HPP 2 | #define PROGRESSBAR_PROGRESSBAR_HPP 3 | 4 | #include 5 | #include 6 | 7 | class ProgressBar { 8 | private: 9 | unsigned int ticks = 0; 10 | 11 | const unsigned int total_ticks; 12 | const unsigned int bar_width; 13 | const char complete_char = '='; 14 | const char incomplete_char = ' '; 15 | const std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now(); 16 | 17 | public: 18 | ProgressBar(unsigned int total, unsigned int width, char complete, char incomplete) : 19 | total_ticks {total}, bar_width {width}, complete_char {complete}, incomplete_char {incomplete} {} 20 | 21 | ProgressBar(unsigned int total, unsigned int width) : total_ticks {total}, bar_width {width} {} 22 | 23 | unsigned int operator++() { return ++ticks; } 24 | 25 | void display() const 26 | { 27 | float progress = (float) ticks / total_ticks; 28 | int pos = (int) (bar_width * progress); 29 | 30 | std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); 31 | auto time_elapsed = std::chrono::duration_cast(now-start_time).count(); 32 | 33 | std::cout << "["; 34 | 35 | for (int i = 0; i < bar_width; ++i) { 36 | if (i < pos) std::cout << complete_char; 37 | else if (i == pos) std::cout << ">"; 38 | else std::cout << incomplete_char; 39 | } 40 | std::cout << "] " << int(progress * 100.0) << "% " 41 | << float(time_elapsed) / 1000.0 << "s\r"; 42 | std::cout.flush(); 43 | } 44 | 45 | void done() const 46 | { 47 | display(); 48 | std::cout << std::endl; 49 | } 50 | }; 51 | 52 | #endif //PROGRESSBAR_PROGRESSBAR_HPP 53 | -------------------------------------------------------------------------------- /src/sptree.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2014, Laurens van der Maaten (Delft University of Technology) 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. All advertising materials mentioning features or use of this software 14 | * must display the following acknowledgement: 15 | * This product includes software developed by the Delft University of Technology. 16 | * 4. Neither the name of the Delft University of Technology nor the names of 17 | * its contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY LAURENS VAN DER MAATEN ''AS IS'' AND ANY EXPRESS 21 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | * EVENT SHALL LAURENS VAN DER MAATEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 28 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 29 | * OF SUCH DAMAGE. 30 | * 31 | */ 32 | 33 | #include "winlibs/stdafx.h" 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "sptree.h" 40 | #include "parallel_for.h" 41 | 42 | 43 | // Constructs cell 44 | Cell::Cell(unsigned int inp_dimension) { 45 | dimension = inp_dimension; 46 | corner = (double *) malloc(dimension * sizeof(double)); 47 | width = (double *) malloc(dimension * sizeof(double)); 48 | } 49 | 50 | Cell::Cell(unsigned int inp_dimension, double *inp_corner, double *inp_width) { 51 | dimension = inp_dimension; 52 | corner = (double *) malloc(dimension * sizeof(double)); 53 | width = (double *) malloc(dimension * sizeof(double)); 54 | for (int d = 0; d < dimension; d++) setCorner(d, inp_corner[d]); 55 | for (int d = 0; d < dimension; d++) setWidth(d, inp_width[d]); 56 | } 57 | 58 | // Destructs cell 59 | Cell::~Cell() { 60 | free(corner); 61 | free(width); 62 | } 63 | 64 | double Cell::getCorner(unsigned int d) { 65 | return corner[d]; 66 | } 67 | 68 | double Cell::getWidth(unsigned int d) { 69 | return width[d]; 70 | } 71 | 72 | void Cell::setCorner(unsigned int d, double val) { 73 | corner[d] = val; 74 | } 75 | 76 | void Cell::setWidth(unsigned int d, double val) { 77 | width[d] = val; 78 | } 79 | 80 | // Checks whether a point lies in a cell 81 | bool Cell::containsPoint(double point[]) { 82 | for (int d = 0; d < dimension; d++) { 83 | if (corner[d] - width[d] > point[d]) return false; 84 | if (corner[d] + width[d] < point[d]) return false; 85 | } 86 | return true; 87 | } 88 | 89 | 90 | // Default constructor for SPTree -- build tree, too! 91 | SPTree::SPTree(unsigned int D, double *inp_data, unsigned int N) { 92 | // Compute mean, width, and height of current map (boundaries of SPTree) 93 | int nD = 0; 94 | double *mean_Y = (double *) calloc(D, sizeof(double)); 95 | double *min_Y = (double *) malloc(D * sizeof(double)); 96 | for (unsigned int d = 0; d < D; d++) min_Y[d] = DBL_MAX; 97 | double *max_Y = (double *) malloc(D * sizeof(double)); 98 | for (unsigned int d = 0; d < D; d++) max_Y[d] = -DBL_MAX; 99 | for (unsigned int n = 0; n < N; n++) { 100 | for (unsigned int d = 0; d < D; d++) { 101 | mean_Y[d] += inp_data[n * D + d]; 102 | if (inp_data[nD + d] < min_Y[d]) min_Y[d] = inp_data[nD + d]; 103 | if (inp_data[nD + d] > max_Y[d]) max_Y[d] = inp_data[nD + d]; 104 | } 105 | nD += D; 106 | } 107 | for (int d = 0; d < D; d++) mean_Y[d] /= (double) N; 108 | 109 | // Construct SPTree 110 | double *width = (double *) malloc(D * sizeof(double)); 111 | for (int d = 0; d < D; d++) width[d] = fmax(max_Y[d] - mean_Y[d], mean_Y[d] - min_Y[d]) + 1e-5; 112 | init(NULL, D, inp_data, mean_Y, width); 113 | fill(N); 114 | 115 | // Clean up memory 116 | free(mean_Y); 117 | free(max_Y); 118 | free(min_Y); 119 | free(width); 120 | } 121 | 122 | 123 | // Constructor for SPTree with particular size and parent -- build the tree, too! 124 | SPTree::SPTree(unsigned int D, double *inp_data, unsigned int N, double *inp_corner, double *inp_width) { 125 | init(NULL, D, inp_data, inp_corner, inp_width); 126 | fill(N); 127 | } 128 | 129 | 130 | // Constructor for SPTree with particular size (do not fill the tree) 131 | SPTree::SPTree(unsigned int D, double *inp_data, double *inp_corner, double *inp_width) { 132 | init(NULL, D, inp_data, inp_corner, inp_width); 133 | } 134 | 135 | 136 | // Constructor for SPTree with particular size and parent (do not fill tree) 137 | SPTree::SPTree(SPTree *inp_parent, unsigned int D, double *inp_data, double *inp_corner, double *inp_width) { 138 | init(inp_parent, D, inp_data, inp_corner, inp_width); 139 | } 140 | 141 | 142 | // Constructor for SPTree with particular size and parent -- build the tree, too! 143 | SPTree::SPTree(SPTree *inp_parent, unsigned int D, double *inp_data, unsigned int N, double *inp_corner, 144 | double *inp_width) { 145 | init(inp_parent, D, inp_data, inp_corner, inp_width); 146 | fill(N); 147 | } 148 | 149 | 150 | // Main initialization function 151 | void SPTree::init(SPTree *inp_parent, unsigned int D, double *inp_data, double *inp_corner, double *inp_width) { 152 | parent = inp_parent; 153 | dimension = D; 154 | no_children = 2; 155 | for (unsigned int d = 1; d < D; d++) no_children *= 2; 156 | data = inp_data; 157 | is_leaf = true; 158 | size = 0; 159 | cum_size = 0; 160 | 161 | boundary = new Cell(dimension); 162 | for (unsigned int d = 0; d < D; d++) boundary->setCorner(d, inp_corner[d]); 163 | for (unsigned int d = 0; d < D; d++) boundary->setWidth(d, inp_width[d]); 164 | 165 | children = (SPTree **) malloc(no_children * sizeof(SPTree *)); 166 | for (unsigned int i = 0; i < no_children; i++) children[i] = NULL; 167 | 168 | center_of_mass = (double *) malloc(D * sizeof(double)); 169 | for (unsigned int d = 0; d < D; d++) center_of_mass[d] = .0; 170 | } 171 | 172 | 173 | // Destructor for SPTree 174 | SPTree::~SPTree() { 175 | for (unsigned int i = 0; i < no_children; i++) { 176 | if (children[i] != NULL) delete children[i]; 177 | } 178 | free(children); 179 | free(center_of_mass); 180 | delete boundary; 181 | } 182 | 183 | 184 | // Update the data underlying this tree 185 | void SPTree::setData(double *inp_data) { 186 | data = inp_data; 187 | } 188 | 189 | 190 | // Get the parent of the current tree 191 | SPTree *SPTree::getParent() { 192 | return parent; 193 | } 194 | 195 | 196 | // Insert a point into the SPTree 197 | bool SPTree::insert(unsigned int new_index) { 198 | // Ignore objects which do not belong in this quad tree 199 | double *point = data + new_index * dimension; 200 | if (!boundary->containsPoint(point)) 201 | return false; 202 | 203 | // Online update of cumulative size and center-of-mass 204 | cum_size++; 205 | double mult1 = (double) (cum_size - 1) / (double) cum_size; 206 | double mult2 = 1.0 / (double) cum_size; 207 | for (unsigned int d = 0; d < dimension; d++) center_of_mass[d] *= mult1; 208 | for (unsigned int d = 0; d < dimension; d++) center_of_mass[d] += mult2 * point[d]; 209 | 210 | // If there is space in this quad tree and it is a leaf, add the object here 211 | if (is_leaf && size < QT_NODE_CAPACITY) { 212 | index[size] = new_index; 213 | size++; 214 | return true; 215 | } 216 | 217 | // Don't add duplicates for now (this is not very nice) 218 | bool any_duplicate = false; 219 | for (unsigned int n = 0; n < size; n++) { 220 | bool duplicate = true; 221 | for (unsigned int d = 0; d < dimension; d++) { 222 | if (point[d] != data[index[n] * dimension + d]) { 223 | duplicate = false; 224 | break; 225 | } 226 | } 227 | any_duplicate = any_duplicate | duplicate; 228 | } 229 | if (any_duplicate) return true; 230 | 231 | // Otherwise, we need to subdivide the current cell 232 | if (is_leaf) subdivide(); 233 | 234 | // Find out where the point can be inserted 235 | for (unsigned int i = 0; i < no_children; i++) { 236 | if (children[i]->insert(new_index)) return true; 237 | } 238 | 239 | // Otherwise, the point cannot be inserted (this should never happen) 240 | return false; 241 | } 242 | 243 | 244 | // Create four children which fully divide this cell into four quads of equal area 245 | void SPTree::subdivide() { 246 | // Create new children 247 | double *new_corner = (double *) malloc(dimension * sizeof(double)); 248 | double *new_width = (double *) malloc(dimension * sizeof(double)); 249 | for (unsigned int i = 0; i < no_children; i++) { 250 | unsigned int div = 1; 251 | for (unsigned int d = 0; d < dimension; d++) { 252 | new_width[d] = .5 * boundary->getWidth(d); 253 | if ((i / div) % 2 == 1) new_corner[d] = boundary->getCorner(d) - .5 * boundary->getWidth(d); 254 | else new_corner[d] = boundary->getCorner(d) + .5 * boundary->getWidth(d); 255 | div *= 2; 256 | } 257 | children[i] = new SPTree(this, dimension, data, new_corner, new_width); 258 | } 259 | free(new_corner); 260 | free(new_width); 261 | 262 | // Move existing points to correct children 263 | for (unsigned int i = 0; i < size; i++) { 264 | bool success = false; 265 | for (unsigned int j = 0; j < no_children; j++) { 266 | if (!success) success = children[j]->insert(index[i]); 267 | } 268 | index[i] = -1; 269 | } 270 | 271 | // Empty parent node 272 | size = 0; 273 | is_leaf = false; 274 | } 275 | 276 | 277 | // Build SPTree on dataset 278 | void SPTree::fill(unsigned int N) { 279 | for (unsigned int i = 0; i < N; i++) insert(i); 280 | } 281 | 282 | 283 | // Checks whether the specified tree is correct 284 | bool SPTree::isCorrect() { 285 | for (unsigned int n = 0; n < size; n++) { 286 | double *point = data + index[n] * dimension; 287 | if (!boundary->containsPoint(point)) return false; 288 | } 289 | if (!is_leaf) { 290 | bool correct = true; 291 | for (int i = 0; i < no_children; i++) correct = correct && children[i]->isCorrect(); 292 | return correct; 293 | } else return true; 294 | } 295 | 296 | 297 | // Build a list of all indices in SPTree 298 | void SPTree::getAllIndices(unsigned int *indices) { 299 | getAllIndices(indices, 0); 300 | } 301 | 302 | 303 | // Build a list of all indices in SPTree 304 | unsigned int SPTree::getAllIndices(unsigned int *indices, unsigned int loc) { 305 | // Gather indices in current quadrant 306 | for (unsigned int i = 0; i < size; i++) indices[loc + i] = index[i]; 307 | loc += size; 308 | 309 | // Gather indices in children 310 | if (!is_leaf) { 311 | for (int i = 0; i < no_children; i++) loc = children[i]->getAllIndices(indices, loc); 312 | } 313 | return loc; 314 | } 315 | 316 | 317 | unsigned int SPTree::getDepth() { 318 | if (is_leaf) return 1; 319 | int depth = 0; 320 | for (unsigned int i = 0; i < no_children; i++) depth = fmax(depth, children[i]->getDepth()); 321 | return 1 + depth; 322 | } 323 | 324 | 325 | // Compute non-edge forces using Barnes-Hut algorithm 326 | void SPTree::computeNonEdgeForces(unsigned int point_index, double theta, double neg_f[], double *sum_Q) { 327 | // Make sure that we spend no time on empty nodes or self-interactions 328 | if (cum_size == 0 || (is_leaf && size == 1 && index[0] == point_index)) return; 329 | 330 | // Compute distance between point and center-of-mass 331 | double D = .0; 332 | unsigned int ind = point_index * dimension; 333 | for (unsigned int d = 0; d < dimension; d++) D += (data[ind + d] - center_of_mass[d]) * (data[ind + d] - center_of_mass[d]); 334 | 335 | // Check whether we can use this node as a "summary" 336 | double max_width = 0.0; 337 | double cur_width; 338 | for (unsigned int d = 0; d < dimension; d++) { 339 | cur_width = boundary->getWidth(d); 340 | max_width = (max_width > cur_width) ? max_width : cur_width; 341 | } 342 | if (is_leaf || max_width / sqrt(D) < theta) { 343 | // Compute and add t-SNE force between point and current node 344 | D = 1.0 / (1.0 + D); 345 | double mult = cum_size * D; 346 | *sum_Q += mult; 347 | mult *= D; 348 | for (unsigned int d = 0; d < dimension; d++) neg_f[d] += mult * (data[ind + d] - center_of_mass[d]); 349 | } else { 350 | // Recursively apply Barnes-Hut to children 351 | for (unsigned int i = 0; i < no_children; i++) 352 | children[i]->computeNonEdgeForces(point_index, theta, neg_f, sum_Q); 353 | } 354 | } 355 | 356 | 357 | // Computes edge forces 358 | void SPTree::computeEdgeForces(unsigned int *row_P, unsigned int *col_P, double *val_P, int N, double *pos_f, unsigned int nthreads) { 359 | // Loop over all edges in the graph 360 | 361 | PARALLEL_FOR(nthreads, N, { 362 | unsigned int ind1 = loop_i * dimension; 363 | 364 | for (unsigned int i = row_P[loop_i]; i < row_P[loop_i + 1]; i++) { 365 | // Compute pairwise distance and Q-value 366 | double D = 1.0; 367 | unsigned int ind2 = col_P[i] * dimension; 368 | for (unsigned int d = 0; d < dimension; d++) D += (data[ind1 + d] - data[ind2 + d]) * (data[ind1 + d] - data[ind2 + d]); 369 | D = val_P[i] / D; 370 | 371 | // Sum positive force 372 | for (unsigned int d = 0; d < dimension; d++) pos_f[ind1 + d] += D * (data[ind1 + d] - data[ind2 + d]); 373 | } 374 | }); 375 | } 376 | 377 | 378 | // Print out tree 379 | void SPTree::print() { 380 | if (cum_size == 0) { 381 | printf("Empty node\n"); 382 | return; 383 | } 384 | 385 | if (is_leaf) { 386 | printf("Leaf node; data = ["); 387 | for (int i = 0; i < size; i++) { 388 | double *point = data + index[i] * dimension; 389 | for (int d = 0; d < dimension; d++) printf("%f, ", point[d]); 390 | printf(" (index = %d)", index[i]); 391 | if (i < size - 1) printf("\n"); 392 | else printf("]\n"); 393 | } 394 | } else { 395 | printf("Intersection node with center-of-mass = ["); 396 | for (int d = 0; d < dimension; d++) printf("%f, ", center_of_mass[d]); 397 | printf("]; children are:\n"); 398 | for (int i = 0; i < no_children; i++) children[i]->print(); 399 | } 400 | } 401 | 402 | -------------------------------------------------------------------------------- /src/sptree.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2014, Laurens van der Maaten (Delft University of Technology) 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. All advertising materials mentioning features or use of this software 14 | * must display the following acknowledgement: 15 | * This product includes software developed by the Delft University of Technology. 16 | * 4. Neither the name of the Delft University of Technology nor the names of 17 | * its contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY LAURENS VAN DER MAATEN ''AS IS'' AND ANY EXPRESS 21 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | * EVENT SHALL LAURENS VAN DER MAATEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 28 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 29 | * OF SUCH DAMAGE. 30 | * 31 | */ 32 | 33 | 34 | #ifndef SPTREE_H 35 | #define SPTREE_H 36 | 37 | using namespace std; 38 | 39 | 40 | class Cell { 41 | 42 | unsigned int dimension; 43 | double *corner; 44 | double *width; 45 | 46 | 47 | public: 48 | Cell(unsigned int inp_dimension); 49 | 50 | Cell(unsigned int inp_dimension, double *inp_corner, double *inp_width); 51 | 52 | ~Cell(); 53 | 54 | double getCorner(unsigned int d); 55 | 56 | double getWidth(unsigned int d); 57 | 58 | void setCorner(unsigned int d, double val); 59 | 60 | void setWidth(unsigned int d, double val); 61 | 62 | bool containsPoint(double point[]); 63 | }; 64 | 65 | 66 | class SPTree { 67 | 68 | // Fixed constants 69 | static const unsigned int QT_NODE_CAPACITY = 1; 70 | 71 | // A buffer we use when doing force computations 72 | double *buff; 73 | 74 | // Properties of this node in the tree 75 | SPTree *parent; 76 | unsigned int dimension; 77 | bool is_leaf; 78 | unsigned int size; 79 | unsigned int cum_size; 80 | 81 | // Axis-aligned bounding box stored as a center with half-dimensions to represent the boundaries of this quad tree 82 | Cell *boundary; 83 | 84 | // Indices in this space-partitioning tree node, corresponding center-of-mass, and list of all children 85 | double *data; 86 | double *center_of_mass; 87 | unsigned int index[QT_NODE_CAPACITY]; 88 | 89 | // Children 90 | SPTree **children; 91 | unsigned int no_children; 92 | 93 | public: 94 | SPTree(unsigned int D, double *inp_data, unsigned int N); 95 | 96 | SPTree(unsigned int D, double *inp_data, double *inp_corner, double *inp_width); 97 | 98 | SPTree(unsigned int D, double *inp_data, unsigned int N, double *inp_corner, double *inp_width); 99 | 100 | SPTree(SPTree *inp_parent, unsigned int D, double *inp_data, unsigned int N, double *inp_corner, double *inp_width); 101 | 102 | SPTree(SPTree *inp_parent, unsigned int D, double *inp_data, double *inp_corner, double *inp_width); 103 | 104 | ~SPTree(); 105 | 106 | void setData(double *inp_data); 107 | 108 | SPTree *getParent(); 109 | 110 | void construct(Cell boundary); 111 | 112 | bool insert(unsigned int new_index); 113 | 114 | void subdivide(); 115 | 116 | bool isCorrect(); 117 | 118 | void rebuildTree(); 119 | 120 | void getAllIndices(unsigned int *indices); 121 | 122 | unsigned int getDepth(); 123 | 124 | void computeNonEdgeForces(unsigned int point_index, double theta, double neg_f[], double *sum_Q); 125 | 126 | void computeEdgeForces(unsigned int *row_P, unsigned int *col_P, double *val_P, int N, double *pos_f, unsigned int nthreads); 127 | 128 | void print(); 129 | 130 | private: 131 | void init(SPTree *inp_parent, unsigned int D, double *inp_data, double *inp_corner, double *inp_width); 132 | 133 | void fill(unsigned int N); 134 | 135 | unsigned int getAllIndices(unsigned int *indices, unsigned int loc); 136 | 137 | bool isChild(unsigned int test_index, unsigned int start, unsigned int end); 138 | }; 139 | 140 | #endif 141 | -------------------------------------------------------------------------------- /src/time_code.h: -------------------------------------------------------------------------------- 1 | #ifndef TIME_CODE_H 2 | #define TIME_CODE_H 3 | #include 4 | #if defined(TIME_CODE) 5 | #pragma message "Timing code" 6 | #define INITIALIZE_TIME std::chrono::steady_clock::time_point STARTVAR; 7 | #define START_TIME \ 8 | STARTVAR = std::chrono::steady_clock::now(); 9 | 10 | #define END_TIME(LABEL) { \ 11 | std::chrono::steady_clock::time_point ENDVAR = std::chrono::steady_clock::now(); \ 12 | printf("%s: %ld ms\n",LABEL, std::chrono::duration_cast(ENDVAR-STARTVAR).count()); \ 13 | } 14 | #else 15 | #define INITIALIZE_TIME 16 | #define START_TIME 17 | #define END_TIME(LABEL) {} 18 | 19 | #endif 20 | #endif 21 | -------------------------------------------------------------------------------- /src/tsne.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2014, Laurens van der Maaten (Delft University of Technology) 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. All advertising materials mentioning features or use of this software 14 | * must display the following acknowledgement: 15 | * This product includes software developed by the Delft University of Technology. 16 | * 4. Neither the name of the Delft University of Technology nor the names of 17 | * its contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY LAURENS VAN DER MAATEN ''AS IS'' AND ANY EXPRESS 21 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | * EVENT SHALL LAURENS VAN DER MAATEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 28 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 29 | * OF SUCH DAMAGE. 30 | * 31 | */ 32 | 33 | 34 | #ifndef TSNE_H 35 | #define TSNE_H 36 | 37 | static inline double sign(double x) { return (x == .0 ? .0 : (x < .0 ? -1.0 : 1.0)); } 38 | 39 | class TSNE { 40 | 41 | public: 42 | int run(double *X, int N, int D, double *Y, int no_dims, double perplexity, double theta, int rand_seed, 43 | bool skip_random_init, int max_iter, int stop_lying_iter, int mom_switch_iter, 44 | double momentum, double final_momentum, double learning_rate, int K, double sigma, 45 | int nbody_algorithm, int knn_algo, double early_exag_coeff, double *costs, 46 | bool no_momentum_during_exag, int start_late_exag_iter, double late_exag_coeff, int n_trees, int search_k, 47 | int nterms, double intervals_per_integer, int min_num_intervals, unsigned int nthreads, int load_affinities, 48 | int perplexity_list_length, double *perplexity_list, double df, double max_step_norm); 49 | 50 | bool load_data(const char *data_path, double **data, double **Y, int *n, int *d, int *no_dims, double *theta, 51 | double *perplexity, int *rand_seed, int *max_iter, int *stop_lying_iter, 52 | int *mom_switch_iter, double* momentum, double* final_momentum, double* learning_rate, int *K, double *sigma, 53 | int *nbody_algo, int *knn_algo, double* early_exag_coeff, int *no_momentum_during_exag, int *n_trees, 54 | int *search_k, int *start_late_exag_iter, double *late_exag_coeff, int *nterms, 55 | double *intervals_per_integer, int *min_num_intervals, bool *skip_random_init, int *load_affinities, 56 | int *perplexity_list_length, double **perplexity_list, double *df, double *max_step_norm); 57 | 58 | void save_data(const char *result_path, double *data, double *costs, int n, int d, int max_iter); 59 | 60 | void symmetrizeMatrix(unsigned int **row_P, unsigned int **col_P, double **val_P, int N); // should be static! 61 | 62 | private: 63 | double current_sum_Q; 64 | void computeGradient(double *P, unsigned int *inp_row_P, unsigned int *inp_col_P, double *inp_val_P, double *Y, 65 | int N, int D, double *dC, double theta, unsigned int nthreads); 66 | 67 | void computeFftGradientVariableDf(double *P, unsigned int *inp_row_P, unsigned int *inp_col_P, double *inp_val_P, double *Y, 68 | int N, int D, double *dC, int n_interpolation_points, double intervals_per_integer, 69 | int min_num_intervals, unsigned int nthreads, double df); 70 | 71 | void computeFftGradient(double *P, unsigned int *inp_row_P, unsigned int *inp_col_P, double *inp_val_P, double *Y, 72 | int N, int D, double *dC, int n_interpolation_points, double intervals_per_integer, 73 | int min_num_intervals, unsigned int nthreads); 74 | 75 | void computeFftGradientOneDVariableDf(double *P, unsigned int *inp_row_P, unsigned int *inp_col_P, double *inp_val_P, 76 | double *Y, int N, int D, double *dC, int n_interpolation_points, 77 | double intervals_per_integer, int min_num_intervals, unsigned int nthreads, double df); 78 | 79 | void computeFftGradientOneD(double *P, unsigned int *inp_row_P, unsigned int *inp_col_P, double *inp_val_P, 80 | double *Y, int N, int D, double *dC, int n_interpolation_points, 81 | double intervals_per_integer, int min_num_intervals, unsigned int nthreads); 82 | 83 | void computeExactGradient(double *P, double *Y, int N, int D, double *dC, double df); 84 | 85 | void computeExactGradientTest(double *Y, int N, int D, double df); 86 | 87 | double evaluateError(double *P, double *Y, int N, int D, double df); 88 | 89 | double evaluateError(unsigned int *row_P, unsigned int *col_P, double *val_P, double *Y, int N, int D, 90 | double theta, unsigned int nthreads); 91 | 92 | double evaluateErrorFft(unsigned int *row_P, unsigned int *col_P, double *val_P, double *Y, int N, int D, unsigned int nthreads, double df); 93 | void zeroMean(double *X, int N, int D); 94 | 95 | double distances2similarities(double *D, double *P, int N, int n, double perplexity, double sigma, bool ifSquared); 96 | 97 | double distances2similarities(double *D, double *P, int N, int n, double perplexity, double sigma, bool ifSquared, 98 | int perplexity_list_length, double *perplexity_list); 99 | 100 | void computeGaussianPerplexity(double *X, int N, int D, double *P, double perplexity, double sigma, 101 | int perplexity_list_length, double *perplexity_list); 102 | 103 | void computeGaussianPerplexity(double *X, int N, int D, unsigned int **_row_P, unsigned int **_col_P, 104 | double **_val_P, double perplexity, int K, double sigma, unsigned int nthreads, 105 | int perplexity_list_length, double *perplexity_list); 106 | 107 | int computeGaussianPerplexity(double *X, int N, int D, unsigned int **_row_P, unsigned int **_col_P, 108 | double **_val_P, double perplexity, int K, double sigma, int num_trees, int search_k, 109 | unsigned int nthreads, int perplexity_list_length, double *perplexity_list, 110 | int rand_seed); 111 | 112 | void computeSquaredEuclideanDistance(double *X, int N, int D, double *DD); 113 | 114 | double randn(); 115 | }; 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /src/vptree.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Copyright (c) 2014, Laurens van der Maaten (Delft University of Technology) 4 | * All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. All advertising materials mentioning features or use of this software 14 | * must display the following acknowledgement: 15 | * This product includes software developed by the Delft University of Technology. 16 | * 4. Neither the name of the Delft University of Technology nor the names of 17 | * its contributors may be used to endorse or promote products derived from 18 | * this software without specific prior written permission. 19 | * 20 | * THIS SOFTWARE IS PROVIDED BY LAURENS VAN DER MAATEN ''AS IS'' AND ANY EXPRESS 21 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 23 | * EVENT SHALL LAURENS VAN DER MAATEN BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 26 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 28 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 29 | * OF SUCH DAMAGE. 30 | * 31 | */ 32 | 33 | 34 | /* This code was adopted with minor modifications from Steve Hanov's great tutorial at http://stevehanov.ca/blog/index.php?id=130 */ 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | 45 | #ifndef VPTREE_H 46 | #define VPTREE_H 47 | 48 | class DataPoint { 49 | int _ind; 50 | 51 | public: 52 | double *_x; 53 | int _D; 54 | 55 | DataPoint() { 56 | _D = 1; 57 | _ind = -1; 58 | _x = NULL; 59 | } 60 | 61 | DataPoint(int D, int ind, double *x) { 62 | _D = D; 63 | _ind = ind; 64 | _x = (double *) malloc(_D * sizeof(double)); 65 | for (int d = 0; d < _D; d++) _x[d] = x[d]; 66 | } 67 | 68 | DataPoint(const DataPoint &other) { // this makes a deep copy -- should not free anything 69 | if (this != &other) { 70 | _D = other.dimensionality(); 71 | _ind = other.index(); 72 | _x = (double *) malloc(_D * sizeof(double)); 73 | for (int d = 0; d < _D; d++) _x[d] = other.x(d); 74 | } 75 | } 76 | 77 | ~DataPoint() { if (_x != NULL) free(_x); } 78 | 79 | DataPoint &operator=(const DataPoint &other) { // asignment should free old object 80 | if (this != &other) { 81 | if (_x != NULL) free(_x); 82 | _D = other.dimensionality(); 83 | _ind = other.index(); 84 | _x = (double *) malloc(_D * sizeof(double)); 85 | for (int d = 0; d < _D; d++) _x[d] = other.x(d); 86 | } 87 | return *this; 88 | } 89 | 90 | int index() const { return _ind; } 91 | 92 | int dimensionality() const { return _D; } 93 | 94 | double x(int d) const { return _x[d]; } 95 | }; 96 | 97 | double euclidean_distance(const DataPoint &t1, const DataPoint &t2) { 98 | double dd = .0; 99 | double *x1 = t1._x; 100 | double *x2 = t2._x; 101 | double diff; 102 | for (int d = 0; d < t1._D; d++) { 103 | diff = (x1[d] - x2[d]); 104 | dd += diff * diff; 105 | } 106 | return sqrt(dd); 107 | } 108 | 109 | 110 | template 111 | class VpTree { 112 | public: 113 | 114 | // Default constructor 115 | VpTree() : _root(0) {} 116 | 117 | // Destructor 118 | ~VpTree() { 119 | delete _root; 120 | } 121 | 122 | // Function to create a new VpTree from data 123 | void create(const std::vector &items) { 124 | delete _root; 125 | _items = items; 126 | _root = buildFromPoints(0, items.size()); 127 | } 128 | 129 | // Function that uses the tree to find the k nearest neighbors of target 130 | void search(const T &target, int k, std::vector *results, std::vector *distances) { 131 | 132 | // Use a priority queue to store intermediate results on 133 | std::priority_queue heap; 134 | 135 | // Variable that tracks the distance to the farthest point in our results 136 | 137 | // Perform the search 138 | double _tau = DBL_MAX; 139 | search(_root, target, k, heap, _tau); 140 | 141 | // Gather final results 142 | results->clear(); 143 | distances->clear(); 144 | while (!heap.empty()) { 145 | results->push_back(_items[heap.top().index]); 146 | distances->push_back(heap.top().dist); 147 | heap.pop(); 148 | } 149 | 150 | // Results are in reverse order 151 | std::reverse(results->begin(), results->end()); 152 | std::reverse(distances->begin(), distances->end()); 153 | } 154 | 155 | private: 156 | std::vector _items; 157 | 158 | // Single node of a VP tree (has a point and radius; left children are closer to point than the radius) 159 | struct Node { 160 | int index; // index of point in node 161 | double threshold; // radius(?) 162 | Node *left; // points closer by than threshold 163 | Node *right; // points farther away than threshold 164 | 165 | Node() : 166 | index(0), threshold(0.), left(0), right(0) {} 167 | 168 | ~Node() { // destructor 169 | delete left; 170 | delete right; 171 | } 172 | } *_root; 173 | 174 | 175 | // An item on the intermediate result queue 176 | struct HeapItem { 177 | HeapItem(int index, double dist) : 178 | index(index), dist(dist) {} 179 | 180 | int index; 181 | double dist; 182 | 183 | bool operator<(const HeapItem &o) const { 184 | return dist < o.dist; 185 | } 186 | }; 187 | 188 | // Distance comparator for use in std::nth_element 189 | struct DistanceComparator { 190 | const T &item; 191 | 192 | DistanceComparator(const T &item) : item(item) {} 193 | 194 | bool operator()(const T &a, const T &b) { 195 | return distance(item, a) < distance(item, b); 196 | } 197 | }; 198 | 199 | // Function that (recursively) fills the tree 200 | Node *buildFromPoints(int lower, int upper) { 201 | if (upper == lower) { // indicates that we're done here! 202 | return NULL; 203 | } 204 | 205 | // Lower index is center of current node 206 | Node *node = new Node(); 207 | node->index = lower; 208 | 209 | if (upper - lower > 1) { // if we did not arrive at leaf yet 210 | 211 | // Choose an arbitrary point and move it to the start 212 | int i = (int) ((double) rand() / RAND_MAX * (upper - lower - 1)) + lower; 213 | std::swap(_items[lower], _items[i]); 214 | 215 | // Partition around the median distance 216 | int median = (upper + lower) / 2; 217 | std::nth_element(_items.begin() + lower + 1, 218 | _items.begin() + median, 219 | _items.begin() + upper, 220 | DistanceComparator(_items[lower])); 221 | 222 | // Threshold of the new node will be the distance to the median 223 | node->threshold = distance(_items[lower], _items[median]); 224 | 225 | // Recursively build tree 226 | node->index = lower; 227 | node->left = buildFromPoints(lower + 1, median); 228 | node->right = buildFromPoints(median, upper); 229 | } 230 | 231 | // Return result 232 | return node; 233 | } 234 | 235 | // Helper function that searches the tree 236 | void search(Node *node, const T &target, int k, std::priority_queue &heap, double &_tau) { 237 | if (node == NULL) return; // indicates that we're done here 238 | 239 | // Compute distance between target and current node 240 | double dist = distance(_items[node->index], target); 241 | 242 | // If current node within radius tau 243 | if (dist < _tau) { 244 | if (heap.size() == k) 245 | heap.pop(); // remove furthest node from result list (if we already have k results) 246 | heap.push(HeapItem(node->index, dist)); // add current node to result list 247 | if (heap.size() == k) _tau = heap.top().dist; // update value of tau (farthest point in result list) 248 | } 249 | 250 | // Return if we arrived at a leaf 251 | if (node->left == NULL && node->right == NULL) { 252 | return; 253 | } 254 | 255 | // If the target lies within the radius of ball 256 | if (dist < node->threshold) { 257 | if (dist - _tau <= 258 | node->threshold) { // if there can still be neighbors inside the ball, recursively search left child first 259 | search(node->left, target, k, heap, _tau); 260 | } 261 | 262 | if (dist + _tau >= 263 | node->threshold) { // if there can still be neighbors outside the ball, recursively search right child 264 | search(node->right, target, k, heap, _tau); 265 | } 266 | 267 | // If the target lies outsize the radius of the ball 268 | } else { 269 | if (dist + _tau >= 270 | node->threshold) { // if there can still be neighbors outside the ball, recursively search right child first 271 | search(node->right, target, k, heap, _tau); 272 | } 273 | 274 | if (dist - _tau <= 275 | node->threshold) { // if there can still be neighbors inside the ball, recursively search left child 276 | search(node->left, target, k, heap, _tau); 277 | } 278 | } 279 | } 280 | }; 281 | 282 | #endif 283 | -------------------------------------------------------------------------------- /src/winlibs/fftw/fftw3.f: -------------------------------------------------------------------------------- 1 | INTEGER FFTW_R2HC 2 | PARAMETER (FFTW_R2HC=0) 3 | INTEGER FFTW_HC2R 4 | PARAMETER (FFTW_HC2R=1) 5 | INTEGER FFTW_DHT 6 | PARAMETER (FFTW_DHT=2) 7 | INTEGER FFTW_REDFT00 8 | PARAMETER (FFTW_REDFT00=3) 9 | INTEGER FFTW_REDFT01 10 | PARAMETER (FFTW_REDFT01=4) 11 | INTEGER FFTW_REDFT10 12 | PARAMETER (FFTW_REDFT10=5) 13 | INTEGER FFTW_REDFT11 14 | PARAMETER (FFTW_REDFT11=6) 15 | INTEGER FFTW_RODFT00 16 | PARAMETER (FFTW_RODFT00=7) 17 | INTEGER FFTW_RODFT01 18 | PARAMETER (FFTW_RODFT01=8) 19 | INTEGER FFTW_RODFT10 20 | PARAMETER (FFTW_RODFT10=9) 21 | INTEGER FFTW_RODFT11 22 | PARAMETER (FFTW_RODFT11=10) 23 | INTEGER FFTW_FORWARD 24 | PARAMETER (FFTW_FORWARD=-1) 25 | INTEGER FFTW_BACKWARD 26 | PARAMETER (FFTW_BACKWARD=+1) 27 | INTEGER FFTW_MEASURE 28 | PARAMETER (FFTW_MEASURE=0) 29 | INTEGER FFTW_DESTROY_INPUT 30 | PARAMETER (FFTW_DESTROY_INPUT=1) 31 | INTEGER FFTW_UNALIGNED 32 | PARAMETER (FFTW_UNALIGNED=2) 33 | INTEGER FFTW_CONSERVE_MEMORY 34 | PARAMETER (FFTW_CONSERVE_MEMORY=4) 35 | INTEGER FFTW_EXHAUSTIVE 36 | PARAMETER (FFTW_EXHAUSTIVE=8) 37 | INTEGER FFTW_PRESERVE_INPUT 38 | PARAMETER (FFTW_PRESERVE_INPUT=16) 39 | INTEGER FFTW_PATIENT 40 | PARAMETER (FFTW_PATIENT=32) 41 | INTEGER FFTW_ESTIMATE 42 | PARAMETER (FFTW_ESTIMATE=64) 43 | INTEGER FFTW_WISDOM_ONLY 44 | PARAMETER (FFTW_WISDOM_ONLY=2097152) 45 | INTEGER FFTW_ESTIMATE_PATIENT 46 | PARAMETER (FFTW_ESTIMATE_PATIENT=128) 47 | INTEGER FFTW_BELIEVE_PCOST 48 | PARAMETER (FFTW_BELIEVE_PCOST=256) 49 | INTEGER FFTW_NO_DFT_R2HC 50 | PARAMETER (FFTW_NO_DFT_R2HC=512) 51 | INTEGER FFTW_NO_NONTHREADED 52 | PARAMETER (FFTW_NO_NONTHREADED=1024) 53 | INTEGER FFTW_NO_BUFFERING 54 | PARAMETER (FFTW_NO_BUFFERING=2048) 55 | INTEGER FFTW_NO_INDIRECT_OP 56 | PARAMETER (FFTW_NO_INDIRECT_OP=4096) 57 | INTEGER FFTW_ALLOW_LARGE_GENERIC 58 | PARAMETER (FFTW_ALLOW_LARGE_GENERIC=8192) 59 | INTEGER FFTW_NO_RANK_SPLITS 60 | PARAMETER (FFTW_NO_RANK_SPLITS=16384) 61 | INTEGER FFTW_NO_VRANK_SPLITS 62 | PARAMETER (FFTW_NO_VRANK_SPLITS=32768) 63 | INTEGER FFTW_NO_VRECURSE 64 | PARAMETER (FFTW_NO_VRECURSE=65536) 65 | INTEGER FFTW_NO_SIMD 66 | PARAMETER (FFTW_NO_SIMD=131072) 67 | INTEGER FFTW_NO_SLOW 68 | PARAMETER (FFTW_NO_SLOW=262144) 69 | INTEGER FFTW_NO_FIXED_RADIX_LARGE_N 70 | PARAMETER (FFTW_NO_FIXED_RADIX_LARGE_N=524288) 71 | INTEGER FFTW_ALLOW_PRUNING 72 | PARAMETER (FFTW_ALLOW_PRUNING=1048576) 73 | -------------------------------------------------------------------------------- /src/winlibs/fftw/fftw3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003, 2007-14 Matteo Frigo 3 | * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology 4 | * 5 | * The following statement of license applies *only* to this header file, 6 | * and *not* to the other files distributed with FFTW or derived therefrom: 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 20 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 25 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | /***************************** NOTE TO USERS ********************************* 33 | * 34 | * THIS IS A HEADER FILE, NOT A MANUAL 35 | * 36 | * If you want to know how to use FFTW, please read the manual, 37 | * online at http://www.fftw.org/doc/ and also included with FFTW. 38 | * For a quick start, see the manual's tutorial section. 39 | * 40 | * (Reading header files to learn how to use a library is a habit 41 | * stemming from code lacking a proper manual. Arguably, it's a 42 | * *bad* habit in most cases, because header files can contain 43 | * interfaces that are not part of the public, stable API.) 44 | * 45 | ****************************************************************************/ 46 | 47 | #ifndef FFTW3_H 48 | #define FFTW3_H 49 | 50 | #include 51 | 52 | #ifdef __cplusplus 53 | extern "C" 54 | { 55 | #endif /* __cplusplus */ 56 | 57 | /* If is included, use the C99 complex type. Otherwise 58 | define a type bit-compatible with C99 complex */ 59 | #if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I) 60 | # define FFTW_DEFINE_COMPLEX(R, C) typedef R _Complex C 61 | #else 62 | # define FFTW_DEFINE_COMPLEX(R, C) typedef R C[2] 63 | #endif 64 | 65 | #define FFTW_CONCAT(prefix, name) prefix ## name 66 | #define FFTW_MANGLE_DOUBLE(name) FFTW_CONCAT(fftw_, name) 67 | #define FFTW_MANGLE_FLOAT(name) FFTW_CONCAT(fftwf_, name) 68 | #define FFTW_MANGLE_LONG_DOUBLE(name) FFTW_CONCAT(fftwl_, name) 69 | #define FFTW_MANGLE_QUAD(name) FFTW_CONCAT(fftwq_, name) 70 | 71 | /* IMPORTANT: for Windows compilers, you should add a line 72 | */ 73 | #define FFTW_DLL 74 | /* 75 | here and in kernel/ifftw.h if you are compiling/using FFTW as a 76 | DLL, in order to do the proper importing/exporting, or 77 | alternatively compile with -DFFTW_DLL or the equivalent 78 | command-line flag. This is not necessary under MinGW/Cygwin, where 79 | libtool does the imports/exports automatically. */ 80 | #if defined(FFTW_DLL) && (defined(_WIN32) || defined(__WIN32__)) 81 | /* annoying Windows syntax for shared-library declarations */ 82 | # if defined(COMPILING_FFTW) /* defined in api.h when compiling FFTW */ 83 | # define FFTW_EXTERN extern __declspec(dllexport) 84 | # else /* user is calling FFTW; import symbol */ 85 | # define FFTW_EXTERN extern __declspec(dllimport) 86 | # endif 87 | #else 88 | # define FFTW_EXTERN extern 89 | #endif 90 | 91 | enum fftw_r2r_kind_do_not_use_me { 92 | FFTW_R2HC=0, FFTW_HC2R=1, FFTW_DHT=2, 93 | FFTW_REDFT00=3, FFTW_REDFT01=4, FFTW_REDFT10=5, FFTW_REDFT11=6, 94 | FFTW_RODFT00=7, FFTW_RODFT01=8, FFTW_RODFT10=9, FFTW_RODFT11=10 95 | }; 96 | 97 | struct fftw_iodim_do_not_use_me { 98 | int n; /* dimension size */ 99 | int is; /* input stride */ 100 | int os; /* output stride */ 101 | }; 102 | 103 | #include /* for ptrdiff_t */ 104 | struct fftw_iodim64_do_not_use_me { 105 | ptrdiff_t n; /* dimension size */ 106 | ptrdiff_t is; /* input stride */ 107 | ptrdiff_t os; /* output stride */ 108 | }; 109 | 110 | typedef void (*fftw_write_char_func_do_not_use_me)(char c, void *); 111 | typedef int (*fftw_read_char_func_do_not_use_me)(void *); 112 | 113 | /* 114 | huge second-order macro that defines prototypes for all API 115 | functions. We expand this macro for each supported precision 116 | 117 | X: name-mangling macro 118 | R: real data type 119 | C: complex data type 120 | */ 121 | 122 | #define FFTW_DEFINE_API(X, R, C) \ 123 | \ 124 | FFTW_DEFINE_COMPLEX(R, C); \ 125 | \ 126 | typedef struct X(plan_s) *X(plan); \ 127 | \ 128 | typedef struct fftw_iodim_do_not_use_me X(iodim); \ 129 | typedef struct fftw_iodim64_do_not_use_me X(iodim64); \ 130 | \ 131 | typedef enum fftw_r2r_kind_do_not_use_me X(r2r_kind); \ 132 | \ 133 | typedef fftw_write_char_func_do_not_use_me X(write_char_func); \ 134 | typedef fftw_read_char_func_do_not_use_me X(read_char_func); \ 135 | \ 136 | FFTW_EXTERN void X(execute)(const X(plan) p); \ 137 | \ 138 | FFTW_EXTERN X(plan) X(plan_dft)(int rank, const int *n, \ 139 | C *in, C *out, int sign, unsigned flags); \ 140 | \ 141 | FFTW_EXTERN X(plan) X(plan_dft_1d)(int n, C *in, C *out, int sign, \ 142 | unsigned flags); \ 143 | FFTW_EXTERN X(plan) X(plan_dft_2d)(int n0, int n1, \ 144 | C *in, C *out, int sign, unsigned flags); \ 145 | FFTW_EXTERN X(plan) X(plan_dft_3d)(int n0, int n1, int n2, \ 146 | C *in, C *out, int sign, unsigned flags); \ 147 | \ 148 | FFTW_EXTERN X(plan) X(plan_many_dft)(int rank, const int *n, \ 149 | int howmany, \ 150 | C *in, const int *inembed, \ 151 | int istride, int idist, \ 152 | C *out, const int *onembed, \ 153 | int ostride, int odist, \ 154 | int sign, unsigned flags); \ 155 | \ 156 | FFTW_EXTERN X(plan) X(plan_guru_dft)(int rank, const X(iodim) *dims, \ 157 | int howmany_rank, \ 158 | const X(iodim) *howmany_dims, \ 159 | C *in, C *out, \ 160 | int sign, unsigned flags); \ 161 | FFTW_EXTERN X(plan) X(plan_guru_split_dft)(int rank, const X(iodim) *dims, \ 162 | int howmany_rank, \ 163 | const X(iodim) *howmany_dims, \ 164 | R *ri, R *ii, R *ro, R *io, \ 165 | unsigned flags); \ 166 | \ 167 | FFTW_EXTERN X(plan) X(plan_guru64_dft)(int rank, \ 168 | const X(iodim64) *dims, \ 169 | int howmany_rank, \ 170 | const X(iodim64) *howmany_dims, \ 171 | C *in, C *out, \ 172 | int sign, unsigned flags); \ 173 | FFTW_EXTERN X(plan) X(plan_guru64_split_dft)(int rank, \ 174 | const X(iodim64) *dims, \ 175 | int howmany_rank, \ 176 | const X(iodim64) *howmany_dims, \ 177 | R *ri, R *ii, R *ro, R *io, \ 178 | unsigned flags); \ 179 | \ 180 | FFTW_EXTERN void X(execute_dft)(const X(plan) p, C *in, C *out); \ 181 | FFTW_EXTERN void X(execute_split_dft)(const X(plan) p, R *ri, R *ii, \ 182 | R *ro, R *io); \ 183 | \ 184 | FFTW_EXTERN X(plan) X(plan_many_dft_r2c)(int rank, const int *n, \ 185 | int howmany, \ 186 | R *in, const int *inembed, \ 187 | int istride, int idist, \ 188 | C *out, const int *onembed, \ 189 | int ostride, int odist, \ 190 | unsigned flags); \ 191 | \ 192 | FFTW_EXTERN X(plan) X(plan_dft_r2c)(int rank, const int *n, \ 193 | R *in, C *out, unsigned flags); \ 194 | \ 195 | FFTW_EXTERN X(plan) X(plan_dft_r2c_1d)(int n,R *in,C *out,unsigned flags); \ 196 | FFTW_EXTERN X(plan) X(plan_dft_r2c_2d)(int n0, int n1, \ 197 | R *in, C *out, unsigned flags); \ 198 | FFTW_EXTERN X(plan) X(plan_dft_r2c_3d)(int n0, int n1, \ 199 | int n2, \ 200 | R *in, C *out, unsigned flags); \ 201 | \ 202 | \ 203 | FFTW_EXTERN X(plan) X(plan_many_dft_c2r)(int rank, const int *n, \ 204 | int howmany, \ 205 | C *in, const int *inembed, \ 206 | int istride, int idist, \ 207 | R *out, const int *onembed, \ 208 | int ostride, int odist, \ 209 | unsigned flags); \ 210 | \ 211 | FFTW_EXTERN X(plan) X(plan_dft_c2r)(int rank, const int *n, \ 212 | C *in, R *out, unsigned flags); \ 213 | \ 214 | FFTW_EXTERN X(plan) X(plan_dft_c2r_1d)(int n,C *in,R *out,unsigned flags); \ 215 | FFTW_EXTERN X(plan) X(plan_dft_c2r_2d)(int n0, int n1, \ 216 | C *in, R *out, unsigned flags); \ 217 | FFTW_EXTERN X(plan) X(plan_dft_c2r_3d)(int n0, int n1, \ 218 | int n2, \ 219 | C *in, R *out, unsigned flags); \ 220 | \ 221 | FFTW_EXTERN X(plan) X(plan_guru_dft_r2c)(int rank, const X(iodim) *dims, \ 222 | int howmany_rank, \ 223 | const X(iodim) *howmany_dims, \ 224 | R *in, C *out, \ 225 | unsigned flags); \ 226 | FFTW_EXTERN X(plan) X(plan_guru_dft_c2r)(int rank, const X(iodim) *dims, \ 227 | int howmany_rank, \ 228 | const X(iodim) *howmany_dims, \ 229 | C *in, R *out, \ 230 | unsigned flags); \ 231 | \ 232 | FFTW_EXTERN X(plan) X(plan_guru_split_dft_r2c)( \ 233 | int rank, const X(iodim) *dims, \ 234 | int howmany_rank, \ 235 | const X(iodim) *howmany_dims, \ 236 | R *in, R *ro, R *io, \ 237 | unsigned flags); \ 238 | FFTW_EXTERN X(plan) X(plan_guru_split_dft_c2r)( \ 239 | int rank, const X(iodim) *dims, \ 240 | int howmany_rank, \ 241 | const X(iodim) *howmany_dims, \ 242 | R *ri, R *ii, R *out, \ 243 | unsigned flags); \ 244 | \ 245 | FFTW_EXTERN X(plan) X(plan_guru64_dft_r2c)(int rank, \ 246 | const X(iodim64) *dims, \ 247 | int howmany_rank, \ 248 | const X(iodim64) *howmany_dims, \ 249 | R *in, C *out, \ 250 | unsigned flags); \ 251 | FFTW_EXTERN X(plan) X(plan_guru64_dft_c2r)(int rank, \ 252 | const X(iodim64) *dims, \ 253 | int howmany_rank, \ 254 | const X(iodim64) *howmany_dims, \ 255 | C *in, R *out, \ 256 | unsigned flags); \ 257 | \ 258 | FFTW_EXTERN X(plan) X(plan_guru64_split_dft_r2c)( \ 259 | int rank, const X(iodim64) *dims, \ 260 | int howmany_rank, \ 261 | const X(iodim64) *howmany_dims, \ 262 | R *in, R *ro, R *io, \ 263 | unsigned flags); \ 264 | FFTW_EXTERN X(plan) X(plan_guru64_split_dft_c2r)( \ 265 | int rank, const X(iodim64) *dims, \ 266 | int howmany_rank, \ 267 | const X(iodim64) *howmany_dims, \ 268 | R *ri, R *ii, R *out, \ 269 | unsigned flags); \ 270 | \ 271 | FFTW_EXTERN void X(execute_dft_r2c)(const X(plan) p, R *in, C *out); \ 272 | FFTW_EXTERN void X(execute_dft_c2r)(const X(plan) p, C *in, R *out); \ 273 | \ 274 | FFTW_EXTERN void X(execute_split_dft_r2c)(const X(plan) p, \ 275 | R *in, R *ro, R *io); \ 276 | FFTW_EXTERN void X(execute_split_dft_c2r)(const X(plan) p, \ 277 | R *ri, R *ii, R *out); \ 278 | \ 279 | FFTW_EXTERN X(plan) X(plan_many_r2r)(int rank, const int *n, \ 280 | int howmany, \ 281 | R *in, const int *inembed, \ 282 | int istride, int idist, \ 283 | R *out, const int *onembed, \ 284 | int ostride, int odist, \ 285 | const X(r2r_kind) *kind, unsigned flags); \ 286 | \ 287 | FFTW_EXTERN X(plan) X(plan_r2r)(int rank, const int *n, R *in, R *out, \ 288 | const X(r2r_kind) *kind, unsigned flags); \ 289 | \ 290 | FFTW_EXTERN X(plan) X(plan_r2r_1d)(int n, R *in, R *out, \ 291 | X(r2r_kind) kind, unsigned flags); \ 292 | FFTW_EXTERN X(plan) X(plan_r2r_2d)(int n0, int n1, R *in, R *out, \ 293 | X(r2r_kind) kind0, X(r2r_kind) kind1, \ 294 | unsigned flags); \ 295 | FFTW_EXTERN X(plan) X(plan_r2r_3d)(int n0, int n1, int n2, \ 296 | R *in, R *out, X(r2r_kind) kind0, \ 297 | X(r2r_kind) kind1, X(r2r_kind) kind2, \ 298 | unsigned flags); \ 299 | \ 300 | FFTW_EXTERN X(plan) X(plan_guru_r2r)(int rank, const X(iodim) *dims, \ 301 | int howmany_rank, \ 302 | const X(iodim) *howmany_dims, \ 303 | R *in, R *out, \ 304 | const X(r2r_kind) *kind, unsigned flags); \ 305 | \ 306 | FFTW_EXTERN X(plan) X(plan_guru64_r2r)(int rank, const X(iodim64) *dims, \ 307 | int howmany_rank, \ 308 | const X(iodim64) *howmany_dims, \ 309 | R *in, R *out, \ 310 | const X(r2r_kind) *kind, unsigned flags); \ 311 | \ 312 | FFTW_EXTERN void X(execute_r2r)(const X(plan) p, R *in, R *out); \ 313 | \ 314 | FFTW_EXTERN void X(destroy_plan)(X(plan) p); \ 315 | FFTW_EXTERN void X(forget_wisdom)(void); \ 316 | FFTW_EXTERN void X(cleanup)(void); \ 317 | \ 318 | FFTW_EXTERN void X(set_timelimit)(double t); \ 319 | \ 320 | FFTW_EXTERN void X(plan_with_nthreads)(int nthreads); \ 321 | FFTW_EXTERN int X(init_threads)(void); \ 322 | FFTW_EXTERN void X(cleanup_threads)(void); \ 323 | FFTW_EXTERN void X(make_planner_thread_safe)(void); \ 324 | \ 325 | FFTW_EXTERN int X(export_wisdom_to_filename)(const char *filename); \ 326 | FFTW_EXTERN void X(export_wisdom_to_file)(FILE *output_file); \ 327 | FFTW_EXTERN char *X(export_wisdom_to_string)(void); \ 328 | FFTW_EXTERN void X(export_wisdom)(X(write_char_func) write_char, \ 329 | void *data); \ 330 | FFTW_EXTERN int X(import_system_wisdom)(void); \ 331 | FFTW_EXTERN int X(import_wisdom_from_filename)(const char *filename); \ 332 | FFTW_EXTERN int X(import_wisdom_from_file)(FILE *input_file); \ 333 | FFTW_EXTERN int X(import_wisdom_from_string)(const char *input_string); \ 334 | FFTW_EXTERN int X(import_wisdom)(X(read_char_func) read_char, void *data); \ 335 | \ 336 | FFTW_EXTERN void X(fprint_plan)(const X(plan) p, FILE *output_file); \ 337 | FFTW_EXTERN void X(print_plan)(const X(plan) p); \ 338 | FFTW_EXTERN char *X(sprint_plan)(const X(plan) p); \ 339 | \ 340 | FFTW_EXTERN void *X(malloc)(size_t n); \ 341 | FFTW_EXTERN R *X(alloc_real)(size_t n); \ 342 | FFTW_EXTERN C *X(alloc_complex)(size_t n); \ 343 | FFTW_EXTERN void X(free)(void *p); \ 344 | \ 345 | FFTW_EXTERN void X(flops)(const X(plan) p, \ 346 | double *add, double *mul, double *fmas); \ 347 | FFTW_EXTERN double X(estimate_cost)(const X(plan) p); \ 348 | FFTW_EXTERN double X(cost)(const X(plan) p); \ 349 | \ 350 | FFTW_EXTERN int X(alignment_of)(R *p); \ 351 | FFTW_EXTERN const char X(version)[]; \ 352 | FFTW_EXTERN const char X(cc)[]; \ 353 | FFTW_EXTERN const char X(codelet_optim)[]; 354 | 355 | 356 | /* end of FFTW_DEFINE_API macro */ 357 | 358 | FFTW_DEFINE_API(FFTW_MANGLE_DOUBLE, double, fftw_complex) 359 | FFTW_DEFINE_API(FFTW_MANGLE_FLOAT, float, fftwf_complex) 360 | FFTW_DEFINE_API(FFTW_MANGLE_LONG_DOUBLE, long double, fftwl_complex) 361 | 362 | /* __float128 (quad precision) is a gcc extension on i386, x86_64, and ia64 363 | for gcc >= 4.6 (compiled in FFTW with --enable-quad-precision) */ 364 | #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) \ 365 | && !(defined(__ICC) || defined(__INTEL_COMPILER) || defined(__CUDACC__) || defined(__PGI)) \ 366 | && (defined(__i386__) || defined(__x86_64__) || defined(__ia64__)) 367 | # if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I) 368 | /* note: __float128 is a typedef, which is not supported with the _Complex 369 | keyword in gcc, so instead we use this ugly __attribute__ version. 370 | However, we can't simply pass the __attribute__ version to 371 | FFTW_DEFINE_API because the __attribute__ confuses gcc in pointer 372 | types. Hence redefining FFTW_DEFINE_COMPLEX. Ugh. */ 373 | # undef FFTW_DEFINE_COMPLEX 374 | # define FFTW_DEFINE_COMPLEX(R, C) typedef _Complex float __attribute__((mode(TC))) C 375 | # endif 376 | FFTW_DEFINE_API(FFTW_MANGLE_QUAD, __float128, fftwq_complex) 377 | #endif 378 | 379 | #define FFTW_FORWARD (-1) 380 | #define FFTW_BACKWARD (+1) 381 | 382 | #define FFTW_NO_TIMELIMIT (-1.0) 383 | 384 | /* documented flags */ 385 | #define FFTW_MEASURE (0U) 386 | #define FFTW_DESTROY_INPUT (1U << 0) 387 | #define FFTW_UNALIGNED (1U << 1) 388 | #define FFTW_CONSERVE_MEMORY (1U << 2) 389 | #define FFTW_EXHAUSTIVE (1U << 3) /* NO_EXHAUSTIVE is default */ 390 | #define FFTW_PRESERVE_INPUT (1U << 4) /* cancels FFTW_DESTROY_INPUT */ 391 | #define FFTW_PATIENT (1U << 5) /* IMPATIENT is default */ 392 | #define FFTW_ESTIMATE (1U << 6) 393 | #define FFTW_WISDOM_ONLY (1U << 21) 394 | 395 | /* undocumented beyond-guru flags */ 396 | #define FFTW_ESTIMATE_PATIENT (1U << 7) 397 | #define FFTW_BELIEVE_PCOST (1U << 8) 398 | #define FFTW_NO_DFT_R2HC (1U << 9) 399 | #define FFTW_NO_NONTHREADED (1U << 10) 400 | #define FFTW_NO_BUFFERING (1U << 11) 401 | #define FFTW_NO_INDIRECT_OP (1U << 12) 402 | #define FFTW_ALLOW_LARGE_GENERIC (1U << 13) /* NO_LARGE_GENERIC is default */ 403 | #define FFTW_NO_RANK_SPLITS (1U << 14) 404 | #define FFTW_NO_VRANK_SPLITS (1U << 15) 405 | #define FFTW_NO_VRECURSE (1U << 16) 406 | #define FFTW_NO_SIMD (1U << 17) 407 | #define FFTW_NO_SLOW (1U << 18) 408 | #define FFTW_NO_FIXED_RADIX_LARGE_N (1U << 19) 409 | #define FFTW_ALLOW_PRUNING (1U << 20) 410 | 411 | #ifdef __cplusplus 412 | } /* extern "C" */ 413 | #endif /* __cplusplus */ 414 | 415 | #endif /* FFTW3_H */ 416 | -------------------------------------------------------------------------------- /src/winlibs/fftw/ffwt_license-and-copyright.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 24 | 25 | FFTW 3.3.8: License and Copyright 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 66 | 67 | 68 | 69 | 70 | 71 | 72 |
73 |

74 | Next: , Previous: , Up: Top   [Contents][Index]

75 |
76 |
77 | 78 |

12 License and Copyright

79 | 80 |

FFTW is Copyright © 2003, 2007-11 Matteo Frigo, Copyright 81 | © 2003, 2007-11 Massachusetts Institute of Technology. 82 |

83 |

FFTW is free software; you can redistribute it and/or modify 84 | it under the terms of the GNU General Public License as published by 85 | the Free Software Foundation; either version 2 of the License, or 86 | (at your option) any later version. 87 |

88 |

This program is distributed in the hope that it will be useful, 89 | but WITHOUT ANY WARRANTY; without even the implied warranty of 90 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 91 | GNU General Public License for more details. 92 |

93 |

You should have received a copy of the GNU General Public License along 94 | with this program; if not, write to the Free Software Foundation, Inc., 95 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA You can also 96 | find the GPL on the GNU 97 | web site. 98 |

99 |

In addition, we kindly ask you to acknowledge FFTW and its authors in 100 | any program or publication in which you use FFTW. (You are not 101 | required to do so; it is up to your common sense to decide 102 | whether you want to comply with this request or not.) For general 103 | publications, we suggest referencing: Matteo Frigo and Steven 104 | G. Johnson, “The design and implementation of FFTW3,” 105 | Proc. IEEE 93 (2), 216–231 (2005). 106 |

107 |

Non-free versions of FFTW are available under terms different from those 108 | of the General Public License. (e.g. they do not require you to 109 | accompany any object code using FFTW with the corresponding source 110 | code.) For these alternative terms you must purchase a license from MIT’s 111 | Technology Licensing Office. Users interested in such a license should 112 | contact us (fftw@fftw.org) for more information. 113 |

114 | 115 |
116 |
117 |

118 | Next: , Previous: , Up: Top   [Contents][Index]

119 |
120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /src/winlibs/fftw/libfftw3-3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KlugerLab/FIt-SNE/47ff14f1defc1ff3a8065c8b7baaf45c33e7e0b2/src/winlibs/fftw/libfftw3-3.dll -------------------------------------------------------------------------------- /src/winlibs/fftw/libfftw3-3.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KlugerLab/FIt-SNE/47ff14f1defc1ff3a8065c8b7baaf45c33e7e0b2/src/winlibs/fftw/libfftw3-3.exp -------------------------------------------------------------------------------- /src/winlibs/fftw/libfftw3-3.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KlugerLab/FIt-SNE/47ff14f1defc1ff3a8065c8b7baaf45c33e7e0b2/src/winlibs/fftw/libfftw3-3.lib -------------------------------------------------------------------------------- /src/winlibs/fftw/libfftw3f-3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KlugerLab/FIt-SNE/47ff14f1defc1ff3a8065c8b7baaf45c33e7e0b2/src/winlibs/fftw/libfftw3f-3.dll -------------------------------------------------------------------------------- /src/winlibs/fftw/libfftw3f-3.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KlugerLab/FIt-SNE/47ff14f1defc1ff3a8065c8b7baaf45c33e7e0b2/src/winlibs/fftw/libfftw3f-3.exp -------------------------------------------------------------------------------- /src/winlibs/fftw/libfftw3f-3.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KlugerLab/FIt-SNE/47ff14f1defc1ff3a8065c8b7baaf45c33e7e0b2/src/winlibs/fftw/libfftw3f-3.lib -------------------------------------------------------------------------------- /src/winlibs/fftw/libfftw3l-3.def: -------------------------------------------------------------------------------- 1 | LIBRARY libfftw3l-3.dll 2 | EXPORTS 3 | fftwl_alignment_of 4 | fftwl_alloc_complex 5 | fftwl_alloc_real 6 | fftwl_assertion_failed 7 | fftwl_bufdist 8 | fftwl_choose_radix 9 | fftwl_cleanup 10 | fftwl_cleanup_threads 11 | fftwl_codelet_e01_8 12 | fftwl_codelet_e10_8 13 | fftwl_codelet_hb_10 14 | fftwl_codelet_hb_12 15 | fftwl_codelet_hb_15 16 | fftwl_codelet_hb_16 17 | fftwl_codelet_hb_2 18 | fftwl_codelet_hb_20 19 | fftwl_codelet_hb2_16 20 | fftwl_codelet_hb2_20 21 | fftwl_codelet_hb2_25 22 | fftwl_codelet_hb2_32 23 | fftwl_codelet_hb2_4 24 | fftwl_codelet_hb_25 25 | fftwl_codelet_hb2_5 26 | fftwl_codelet_hb2_8 27 | fftwl_codelet_hb_3 28 | fftwl_codelet_hb_32 29 | fftwl_codelet_hb_4 30 | fftwl_codelet_hb_5 31 | fftwl_codelet_hb_6 32 | fftwl_codelet_hb_64 33 | fftwl_codelet_hb_7 34 | fftwl_codelet_hb_8 35 | fftwl_codelet_hb_9 36 | fftwl_codelet_hc2cb_10 37 | fftwl_codelet_hc2cb_12 38 | fftwl_codelet_hc2cb_16 39 | fftwl_codelet_hc2cb_2 40 | fftwl_codelet_hc2cb_20 41 | fftwl_codelet_hc2cb2_16 42 | fftwl_codelet_hc2cb2_20 43 | fftwl_codelet_hc2cb2_32 44 | fftwl_codelet_hc2cb2_4 45 | fftwl_codelet_hc2cb2_8 46 | fftwl_codelet_hc2cb_32 47 | fftwl_codelet_hc2cb_4 48 | fftwl_codelet_hc2cb_6 49 | fftwl_codelet_hc2cb_8 50 | fftwl_codelet_hc2cbdft_10 51 | fftwl_codelet_hc2cbdft_12 52 | fftwl_codelet_hc2cbdft_16 53 | fftwl_codelet_hc2cbdft_2 54 | fftwl_codelet_hc2cbdft_20 55 | fftwl_codelet_hc2cbdft2_16 56 | fftwl_codelet_hc2cbdft2_20 57 | fftwl_codelet_hc2cbdft2_32 58 | fftwl_codelet_hc2cbdft2_4 59 | fftwl_codelet_hc2cbdft2_8 60 | fftwl_codelet_hc2cbdft_32 61 | fftwl_codelet_hc2cbdft_4 62 | fftwl_codelet_hc2cbdft_6 63 | fftwl_codelet_hc2cbdft_8 64 | fftwl_codelet_hc2cf_10 65 | fftwl_codelet_hc2cf_12 66 | fftwl_codelet_hc2cf_16 67 | fftwl_codelet_hc2cf_2 68 | fftwl_codelet_hc2cf_20 69 | fftwl_codelet_hc2cf2_16 70 | fftwl_codelet_hc2cf2_20 71 | fftwl_codelet_hc2cf2_32 72 | fftwl_codelet_hc2cf2_4 73 | fftwl_codelet_hc2cf2_8 74 | fftwl_codelet_hc2cf_32 75 | fftwl_codelet_hc2cf_4 76 | fftwl_codelet_hc2cf_6 77 | fftwl_codelet_hc2cf_8 78 | fftwl_codelet_hc2cfdft_10 79 | fftwl_codelet_hc2cfdft_12 80 | fftwl_codelet_hc2cfdft_16 81 | fftwl_codelet_hc2cfdft_2 82 | fftwl_codelet_hc2cfdft_20 83 | fftwl_codelet_hc2cfdft2_16 84 | fftwl_codelet_hc2cfdft2_20 85 | fftwl_codelet_hc2cfdft2_32 86 | fftwl_codelet_hc2cfdft2_4 87 | fftwl_codelet_hc2cfdft2_8 88 | fftwl_codelet_hc2cfdft_32 89 | fftwl_codelet_hc2cfdft_4 90 | fftwl_codelet_hc2cfdft_6 91 | fftwl_codelet_hc2cfdft_8 92 | fftwl_codelet_hf_10 93 | fftwl_codelet_hf_12 94 | fftwl_codelet_hf_15 95 | fftwl_codelet_hf_16 96 | fftwl_codelet_hf_2 97 | fftwl_codelet_hf_20 98 | fftwl_codelet_hf2_16 99 | fftwl_codelet_hf2_20 100 | fftwl_codelet_hf2_25 101 | fftwl_codelet_hf2_32 102 | fftwl_codelet_hf2_4 103 | fftwl_codelet_hf_25 104 | fftwl_codelet_hf2_5 105 | fftwl_codelet_hf2_8 106 | fftwl_codelet_hf_3 107 | fftwl_codelet_hf_32 108 | fftwl_codelet_hf_4 109 | fftwl_codelet_hf_5 110 | fftwl_codelet_hf_6 111 | fftwl_codelet_hf_64 112 | fftwl_codelet_hf_7 113 | fftwl_codelet_hf_8 114 | fftwl_codelet_hf_9 115 | fftwl_codelet_n1_10 116 | fftwl_codelet_n1_11 117 | fftwl_codelet_n1_12 118 | fftwl_codelet_n1_13 119 | fftwl_codelet_n1_14 120 | fftwl_codelet_n1_15 121 | fftwl_codelet_n1_16 122 | fftwl_codelet_n1_2 123 | fftwl_codelet_n1_20 124 | fftwl_codelet_n1_25 125 | fftwl_codelet_n1_3 126 | fftwl_codelet_n1_32 127 | fftwl_codelet_n1_4 128 | fftwl_codelet_n1_5 129 | fftwl_codelet_n1_6 130 | fftwl_codelet_n1_64 131 | fftwl_codelet_n1_7 132 | fftwl_codelet_n1_8 133 | fftwl_codelet_n1_9 134 | fftwl_codelet_q1_2 135 | fftwl_codelet_q1_3 136 | fftwl_codelet_q1_4 137 | fftwl_codelet_q1_5 138 | fftwl_codelet_q1_6 139 | fftwl_codelet_q1_8 140 | fftwl_codelet_r2cb_10 141 | fftwl_codelet_r2cb_11 142 | fftwl_codelet_r2cb_12 143 | fftwl_codelet_r2cb_128 144 | fftwl_codelet_r2cb_13 145 | fftwl_codelet_r2cb_14 146 | fftwl_codelet_r2cb_15 147 | fftwl_codelet_r2cb_16 148 | fftwl_codelet_r2cb_2 149 | fftwl_codelet_r2cb_20 150 | fftwl_codelet_r2cb_25 151 | fftwl_codelet_r2cb_3 152 | fftwl_codelet_r2cb_32 153 | fftwl_codelet_r2cb_4 154 | fftwl_codelet_r2cb_5 155 | fftwl_codelet_r2cb_6 156 | fftwl_codelet_r2cb_64 157 | fftwl_codelet_r2cb_7 158 | fftwl_codelet_r2cb_8 159 | fftwl_codelet_r2cb_9 160 | fftwl_codelet_r2cbIII_10 161 | fftwl_codelet_r2cbIII_12 162 | fftwl_codelet_r2cbIII_15 163 | fftwl_codelet_r2cbIII_16 164 | fftwl_codelet_r2cbIII_2 165 | fftwl_codelet_r2cbIII_20 166 | fftwl_codelet_r2cbIII_25 167 | fftwl_codelet_r2cbIII_3 168 | fftwl_codelet_r2cbIII_32 169 | fftwl_codelet_r2cbIII_4 170 | fftwl_codelet_r2cbIII_5 171 | fftwl_codelet_r2cbIII_6 172 | fftwl_codelet_r2cbIII_64 173 | fftwl_codelet_r2cbIII_7 174 | fftwl_codelet_r2cbIII_8 175 | fftwl_codelet_r2cbIII_9 176 | fftwl_codelet_r2cf_10 177 | fftwl_codelet_r2cf_11 178 | fftwl_codelet_r2cf_12 179 | fftwl_codelet_r2cf_128 180 | fftwl_codelet_r2cf_13 181 | fftwl_codelet_r2cf_14 182 | fftwl_codelet_r2cf_15 183 | fftwl_codelet_r2cf_16 184 | fftwl_codelet_r2cf_2 185 | fftwl_codelet_r2cf_20 186 | fftwl_codelet_r2cf_25 187 | fftwl_codelet_r2cf_3 188 | fftwl_codelet_r2cf_32 189 | fftwl_codelet_r2cf_4 190 | fftwl_codelet_r2cf_5 191 | fftwl_codelet_r2cf_6 192 | fftwl_codelet_r2cf_64 193 | fftwl_codelet_r2cf_7 194 | fftwl_codelet_r2cf_8 195 | fftwl_codelet_r2cf_9 196 | fftwl_codelet_r2cfII_10 197 | fftwl_codelet_r2cfII_12 198 | fftwl_codelet_r2cfII_15 199 | fftwl_codelet_r2cfII_16 200 | fftwl_codelet_r2cfII_2 201 | fftwl_codelet_r2cfII_20 202 | fftwl_codelet_r2cfII_25 203 | fftwl_codelet_r2cfII_3 204 | fftwl_codelet_r2cfII_32 205 | fftwl_codelet_r2cfII_4 206 | fftwl_codelet_r2cfII_5 207 | fftwl_codelet_r2cfII_6 208 | fftwl_codelet_r2cfII_64 209 | fftwl_codelet_r2cfII_7 210 | fftwl_codelet_r2cfII_8 211 | fftwl_codelet_r2cfII_9 212 | fftwl_codelet_t1_10 213 | fftwl_codelet_t1_12 214 | fftwl_codelet_t1_15 215 | fftwl_codelet_t1_16 216 | fftwl_codelet_t1_2 217 | fftwl_codelet_t1_20 218 | fftwl_codelet_t1_25 219 | fftwl_codelet_t1_3 220 | fftwl_codelet_t1_32 221 | fftwl_codelet_t1_4 222 | fftwl_codelet_t1_5 223 | fftwl_codelet_t1_6 224 | fftwl_codelet_t1_64 225 | fftwl_codelet_t1_7 226 | fftwl_codelet_t1_8 227 | fftwl_codelet_t1_9 228 | fftwl_codelet_t2_10 229 | fftwl_codelet_t2_16 230 | fftwl_codelet_t2_20 231 | fftwl_codelet_t2_25 232 | fftwl_codelet_t2_32 233 | fftwl_codelet_t2_4 234 | fftwl_codelet_t2_5 235 | fftwl_codelet_t2_64 236 | fftwl_codelet_t2_8 237 | fftwl_compute_tilesz 238 | fftwl_configure_planner 239 | fftwl_cost 240 | fftwl_cpy1d 241 | fftwl_cpy2d 242 | fftwl_cpy2d_ci 243 | fftwl_cpy2d_co 244 | fftwl_cpy2d_pair 245 | fftwl_cpy2d_pair_ci 246 | fftwl_cpy2d_pair_co 247 | fftwl_cpy2d_tiled 248 | fftwl_cpy2d_tiledbuf 249 | fftwl_ct_applicable 250 | fftwl_ct_genericbuf_register 251 | fftwl_ct_generic_register 252 | fftwl_ct_uglyp 253 | fftwl_destroy_plan 254 | fftwl_dft_bluestein_register 255 | fftwl_dft_buffered_register 256 | fftwl_dft_conf_standard 257 | fftwl_dft_generic_register 258 | fftwl_dft_indirect_register 259 | fftwl_dft_indirect_transpose_register 260 | fftwl_dft_nop_register 261 | fftwl_dft_r2hc_register 262 | fftwl_dft_rader_register 263 | fftwl_dft_rank_geq2_register 264 | fftwl_dft_solve 265 | fftwl_dft_thr_vrank_geq1_register 266 | fftwl_dft_vrank_geq1_register 267 | fftwl_dft_zerotens 268 | fftwl_dht_r2hc_register 269 | fftwl_dht_rader_register 270 | fftwl_dimcmp 271 | fftwl_elapsed_since 272 | fftwl_estimate_cost 273 | fftwl_execute 274 | fftwl_execute_dft 275 | fftwl_execute_dft_c2r 276 | fftwl_execute_dft_r2c 277 | fftwl_execute_r2r 278 | fftwl_execute_split_dft 279 | fftwl_execute_split_dft_c2r 280 | fftwl_execute_split_dft_r2c 281 | fftwl_export_wisdom 282 | fftwl_export_wisdom_to_file 283 | fftwl_export_wisdom_to_filename 284 | fftwl_export_wisdom_to_string 285 | fftwl_extract_reim 286 | fftwl_factors_into 287 | fftwl_factors_into_small_primes 288 | fftwl_find_generator 289 | fftwl_first_divisor 290 | fftwl_flops 291 | fftwl_forget_wisdom 292 | fftwl_fprint_plan 293 | fftwl_free 294 | fftwl_get_crude_time 295 | fftwl_guru64_kosherp 296 | fftwl_guru_kosherp 297 | fftwl_hash 298 | fftwl_hc2hc_applicable 299 | fftwl_hc2hc_generic_register 300 | fftwl_iabs 301 | fftwl_ialignment_of 302 | fftwl_iestimate_cost 303 | fftwl_ifree 304 | fftwl_ifree0 305 | fftwl_imax 306 | fftwl_imin 307 | fftwl_import_system_wisdom 308 | fftwl_import_wisdom 309 | fftwl_import_wisdom_from_file 310 | fftwl_import_wisdom_from_filename 311 | fftwl_import_wisdom_from_string 312 | fftwl_init_threads 313 | fftwl_is_prime 314 | fftwl_isqrt 315 | fftwl_ithreads_init 316 | fftwl_kdft_dif_register 317 | fftwl_kdft_difsq_register 318 | fftwl_kdft_dit_register 319 | fftwl_kdft_register 320 | fftwl_kernel_free 321 | fftwl_kernel_malloc 322 | fftwl_khc2c_register 323 | fftwl_khc2hc_register 324 | fftwl_kr2c_register 325 | fftwl_kr2r_register 326 | fftwl_make_planner_thread_safe 327 | fftwl_malloc 328 | fftwl_malloc_plain 329 | fftwl_many_kosherp 330 | fftwl_mapflags 331 | fftwl_map_r2r_kind 332 | fftwl_md5begin 333 | fftwl_md5end 334 | fftwl_md5int 335 | fftwl_md5INT 336 | fftwl_md5putb 337 | fftwl_md5putc 338 | fftwl_md5puts 339 | fftwl_md5unsigned 340 | fftwl_measure_execution_time 341 | fftwl_mkapiplan 342 | fftwl_mkplan 343 | fftwl_mkplan_d 344 | fftwl_mkplan_dft 345 | fftwl_mkplan_dftw 346 | fftwl_mkplan_f_d 347 | fftwl_mkplan_hc2c 348 | fftwl_mkplan_hc2hc 349 | fftwl_mkplanner 350 | fftwl_mkplan_rdft 351 | fftwl_mkplan_rdft2 352 | fftwl_mkprinter 353 | fftwl_mkprinter_cnt 354 | fftwl_mkprinter_file 355 | fftwl_mkprinter_str 356 | fftwl_mkproblem 357 | fftwl_mkproblem_dft 358 | fftwl_mkproblem_dft_d 359 | fftwl_mkproblem_rdft 360 | fftwl_mkproblem_rdft_0_d 361 | fftwl_mkproblem_rdft_1 362 | fftwl_mkproblem_rdft_1_d 363 | fftwl_mkproblem_rdft2 364 | fftwl_mkproblem_rdft2_d 365 | fftwl_mkproblem_rdft2_d_3pointers 366 | fftwl_mkproblem_rdft_d 367 | fftwl_mkproblem_unsolvable 368 | fftwl_mkscanner 369 | fftwl_mksolver 370 | fftwl_mksolver_ct 371 | fftwl_mksolver_ct_threads 372 | fftwl_mksolver_dft_direct 373 | fftwl_mksolver_dft_directbuf 374 | fftwl_mksolver_hc2c 375 | fftwl_mksolver_hc2hc 376 | fftwl_mksolver_hc2hc_threads 377 | fftwl_mksolver_rdft2_direct 378 | fftwl_mksolver_rdft_r2c_direct 379 | fftwl_mksolver_rdft_r2c_directbuf 380 | fftwl_mksolver_rdft_r2r_direct 381 | fftwl_mktensor 382 | fftwl_mktensor_0d 383 | fftwl_mktensor_1d 384 | fftwl_mktensor_2d 385 | fftwl_mktensor_3d 386 | fftwl_mktensor_4d 387 | fftwl_mktensor_5d 388 | fftwl_mktensor_iodims 389 | fftwl_mktensor_iodims64 390 | fftwl_mktensor_rowmajor 391 | fftwl_mktriggen 392 | fftwl_modulo 393 | fftwl_nbuf 394 | fftwl_nbuf_redundant 395 | fftwl_next_prime 396 | fftwl_null_awake 397 | fftwl_ops_add 398 | fftwl_ops_add2 399 | fftwl_ops_cpy 400 | fftwl_ops_madd 401 | fftwl_ops_madd2 402 | fftwl_ops_other 403 | fftwl_ops_zero 404 | fftwl_pickdim 405 | fftwl_plan_awake 406 | fftwl_plan_destroy_internal 407 | fftwl_plan_dft 408 | fftwl_plan_dft_1d 409 | fftwl_plan_dft_2d 410 | fftwl_plan_dft_3d 411 | fftwl_plan_dft_c2r 412 | fftwl_plan_dft_c2r_1d 413 | fftwl_plan_dft_c2r_2d 414 | fftwl_plan_dft_c2r_3d 415 | fftwl_plan_dft_r2c 416 | fftwl_plan_dft_r2c_1d 417 | fftwl_plan_dft_r2c_2d 418 | fftwl_plan_dft_r2c_3d 419 | fftwl_plan_guru64_dft 420 | fftwl_plan_guru64_dft_c2r 421 | fftwl_plan_guru64_dft_r2c 422 | fftwl_plan_guru64_r2r 423 | fftwl_plan_guru64_split_dft 424 | fftwl_plan_guru64_split_dft_c2r 425 | fftwl_plan_guru64_split_dft_r2c 426 | fftwl_plan_guru_dft 427 | fftwl_plan_guru_dft_c2r 428 | fftwl_plan_guru_dft_r2c 429 | fftwl_plan_guru_r2r 430 | fftwl_plan_guru_split_dft 431 | fftwl_plan_guru_split_dft_c2r 432 | fftwl_plan_guru_split_dft_r2c 433 | fftwl_plan_many_dft 434 | fftwl_plan_many_dft_c2r 435 | fftwl_plan_many_dft_r2c 436 | fftwl_plan_many_r2r 437 | fftwl_planner_destroy 438 | fftwl_plan_null_destroy 439 | fftwl_plan_r2r 440 | fftwl_plan_r2r_1d 441 | fftwl_plan_r2r_2d 442 | fftwl_plan_r2r_3d 443 | fftwl_plan_with_nthreads 444 | fftwl_power_mod 445 | fftwl_printer_destroy 446 | fftwl_print_plan 447 | fftwl_problem_destroy 448 | fftwl_rader_tl_delete 449 | fftwl_rader_tl_find 450 | fftwl_rader_tl_insert 451 | fftwl_rdft2_buffered_register 452 | fftwl_rdft2_complex_n 453 | fftwl_rdft2_inplace_strides 454 | fftwl_rdft2_nop_register 455 | fftwl_rdft2_pad 456 | fftwl_rdft2_rank0_register 457 | fftwl_rdft2_rank_geq2_register 458 | fftwl_rdft2_rdft_register 459 | fftwl_rdft2_solve 460 | fftwl_rdft2_strides 461 | fftwl_rdft2_tensor_max_index 462 | fftwl_rdft2_thr_vrank_geq1_register 463 | fftwl_rdft2_vrank_geq1_register 464 | fftwl_rdft_buffered_register 465 | fftwl_rdft_conf_standard 466 | fftwl_rdft_dht_register 467 | fftwl_rdft_generic_register 468 | fftwl_rdft_indirect_register 469 | fftwl_rdft_kind_str 470 | fftwl_rdft_nop_register 471 | fftwl_rdft_rank0_register 472 | fftwl_rdft_rank_geq2_register 473 | fftwl_rdft_solve 474 | fftwl_rdft_thr_vrank_geq1_register 475 | fftwl_rdft_vrank3_transpose_register 476 | fftwl_rdft_vrank_geq1_register 477 | fftwl_rdft_zerotens 478 | fftwl_redft00e_r2hc_pad_register 479 | fftwl_regsolver_ct_directw 480 | fftwl_regsolver_ct_directwsq 481 | fftwl_regsolver_hc2c_direct 482 | fftwl_regsolver_hc2hc_direct 483 | fftwl_reodft00e_splitradix_register 484 | fftwl_reodft010e_r2hc_register 485 | fftwl_reodft11e_r2hc_odd_register 486 | fftwl_reodft11e_radix2_r2hc_register 487 | fftwl_reodft_conf_standard 488 | fftwl_rodft00e_r2hc_pad_register 489 | fftwl_safe_mulmod 490 | fftwl_scanner_destroy 491 | fftwl_set_planner_hooks 492 | fftwl_set_timelimit 493 | fftwl_solver_destroy 494 | fftwl_solver_register 495 | fftwl_solver_use 496 | fftwl_solvtab_exec 497 | fftwl_spawn_loop 498 | fftwl_sprint_plan 499 | fftwl_tensor_append 500 | fftwl_tensor_compress 501 | fftwl_tensor_compress_contiguous 502 | fftwl_tensor_copy 503 | fftwl_tensor_copy_except 504 | fftwl_tensor_copy_inplace 505 | fftwl_tensor_copy_sub 506 | fftwl_tensor_destroy 507 | fftwl_tensor_destroy2 508 | fftwl_tensor_destroy4 509 | fftwl_tensor_equal 510 | fftwl_tensor_inplace_locations 511 | fftwl_tensor_inplace_strides 512 | fftwl_tensor_inplace_strides2 513 | fftwl_tensor_kosherp 514 | fftwl_tensor_max_index 515 | fftwl_tensor_md5 516 | fftwl_tensor_min_istride 517 | fftwl_tensor_min_ostride 518 | fftwl_tensor_min_stride 519 | fftwl_tensor_print 520 | fftwl_tensor_split 521 | fftwl_tensor_strides_decrease 522 | fftwl_tensor_sz 523 | fftwl_tensor_tornk1 524 | fftwl_the_planner 525 | fftwl_threads_cleanup 526 | fftwl_threads_conf_standard 527 | fftwl_threads_register_planner_hooks 528 | fftwl_tile2d 529 | fftwl_toobig 530 | fftwl_transpose 531 | fftwl_transpose_tiled 532 | fftwl_transpose_tiledbuf 533 | fftwl_triggen_destroy 534 | fftwl_twiddle_awake 535 | fftwl_twiddle_length 536 | fftwl_zero1d_pair 537 | lfftw_cleanup_ 538 | lfftw_cleanup__ 539 | lfftw_cleanup_threads_ 540 | lfftw_cleanup_threads__ 541 | lfftw_cost_ 542 | lfftw_cost__ 543 | lfftw_destroy_plan_ 544 | lfftw_destroy_plan__ 545 | lfftw_estimate_cost_ 546 | lfftw_estimate_cost__ 547 | lfftw_execute_ 548 | lfftw_execute__ 549 | lfftw_execute_dft_ 550 | lfftw_execute_dft__ 551 | lfftw_execute_dft_c2r_ 552 | lfftw_execute_dft_c2r__ 553 | lfftw_execute_dft_r2c_ 554 | lfftw_execute_dft_r2c__ 555 | lfftw_execute_r2r_ 556 | lfftw_execute_r2r__ 557 | lfftw_execute_split_dft_ 558 | lfftw_execute_split_dft__ 559 | lfftw_execute_split_dft_c2r_ 560 | lfftw_execute_split_dft_c2r__ 561 | lfftw_execute_split_dft_r2c_ 562 | lfftw_execute_split_dft_r2c__ 563 | lfftw_export_wisdom_ 564 | lfftw_export_wisdom__ 565 | lfftw_flops_ 566 | lfftw_flops__ 567 | lfftw_forget_wisdom_ 568 | lfftw_forget_wisdom__ 569 | lfftw_import_system_wisdom_ 570 | lfftw_import_system_wisdom__ 571 | lfftw_import_wisdom_ 572 | lfftw_import_wisdom__ 573 | lfftw_init_threads_ 574 | lfftw_init_threads__ 575 | lfftw_plan_dft_ 576 | lfftw_plan_dft__ 577 | lfftw_plan_dft_1d_ 578 | lfftw_plan_dft_1d__ 579 | lfftw_plan_dft_2d_ 580 | lfftw_plan_dft_2d__ 581 | lfftw_plan_dft_3d_ 582 | lfftw_plan_dft_3d__ 583 | lfftw_plan_dft_c2r_ 584 | lfftw_plan_dft_c2r__ 585 | lfftw_plan_dft_c2r_1d_ 586 | lfftw_plan_dft_c2r_1d__ 587 | lfftw_plan_dft_c2r_2d_ 588 | lfftw_plan_dft_c2r_2d__ 589 | lfftw_plan_dft_c2r_3d_ 590 | lfftw_plan_dft_c2r_3d__ 591 | lfftw_plan_dft_r2c_ 592 | lfftw_plan_dft_r2c__ 593 | lfftw_plan_dft_r2c_1d_ 594 | lfftw_plan_dft_r2c_1d__ 595 | lfftw_plan_dft_r2c_2d_ 596 | lfftw_plan_dft_r2c_2d__ 597 | lfftw_plan_dft_r2c_3d_ 598 | lfftw_plan_dft_r2c_3d__ 599 | lfftw_plan_guru_dft_ 600 | lfftw_plan_guru_dft__ 601 | lfftw_plan_guru_dft_c2r_ 602 | lfftw_plan_guru_dft_c2r__ 603 | lfftw_plan_guru_dft_r2c_ 604 | lfftw_plan_guru_dft_r2c__ 605 | lfftw_plan_guru_r2r_ 606 | lfftw_plan_guru_r2r__ 607 | lfftw_plan_guru_split_dft_ 608 | lfftw_plan_guru_split_dft__ 609 | lfftw_plan_guru_split_dft_c2r_ 610 | lfftw_plan_guru_split_dft_c2r__ 611 | lfftw_plan_guru_split_dft_r2c_ 612 | lfftw_plan_guru_split_dft_r2c__ 613 | lfftw_plan_many_dft_ 614 | lfftw_plan_many_dft__ 615 | lfftw_plan_many_dft_c2r_ 616 | lfftw_plan_many_dft_c2r__ 617 | lfftw_plan_many_dft_r2c_ 618 | lfftw_plan_many_dft_r2c__ 619 | lfftw_plan_many_r2r_ 620 | lfftw_plan_many_r2r__ 621 | lfftw_plan_r2r_ 622 | lfftw_plan_r2r__ 623 | lfftw_plan_r2r_1d_ 624 | lfftw_plan_r2r_1d__ 625 | lfftw_plan_r2r_2d_ 626 | lfftw_plan_r2r_2d__ 627 | lfftw_plan_r2r_3d_ 628 | lfftw_plan_r2r_3d__ 629 | lfftw_plan_with_nthreads_ 630 | lfftw_plan_with_nthreads__ 631 | lfftw_print_plan_ 632 | lfftw_print_plan__ 633 | lfftw_set_timelimit_ 634 | lfftw_set_timelimit__ 635 | -------------------------------------------------------------------------------- /src/winlibs/fftw/libfftw3l-3.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KlugerLab/FIt-SNE/47ff14f1defc1ff3a8065c8b7baaf45c33e7e0b2/src/winlibs/fftw/libfftw3l-3.dll -------------------------------------------------------------------------------- /src/winlibs/fftw/libfftw3l-3.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KlugerLab/FIt-SNE/47ff14f1defc1ff3a8065c8b7baaf45c33e7e0b2/src/winlibs/fftw/libfftw3l-3.exp -------------------------------------------------------------------------------- /src/winlibs/fftw/libfftw3l-3.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KlugerLab/FIt-SNE/47ff14f1defc1ff3a8065c8b7baaf45c33e7e0b2/src/winlibs/fftw/libfftw3l-3.lib -------------------------------------------------------------------------------- /src/winlibs/fftw3.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2003, 2007-14 Matteo Frigo 3 | * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology 4 | * 5 | * The following statement of license applies *only* to this header file, 6 | * and *not* to the other files distributed with FFTW or derived therefrom: 7 | * 8 | * Redistribution and use in source and binary forms, with or without 9 | * modification, are permitted provided that the following conditions 10 | * are met: 11 | * 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 20 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 23 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 25 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 27 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | /***************************** NOTE TO USERS ********************************* 33 | * 34 | * THIS IS A HEADER FILE, NOT A MANUAL 35 | * 36 | * If you want to know how to use FFTW, please read the manual, 37 | * online at http://www.fftw.org/doc/ and also included with FFTW. 38 | * For a quick start, see the manual's tutorial section. 39 | * 40 | * (Reading header files to learn how to use a library is a habit 41 | * stemming from code lacking a proper manual. Arguably, it's a 42 | * *bad* habit in most cases, because header files can contain 43 | * interfaces that are not part of the public, stable API.) 44 | * 45 | ****************************************************************************/ 46 | 47 | #ifndef FFTW3_H 48 | #define FFTW3_H 49 | 50 | #include 51 | 52 | #ifdef __cplusplus 53 | extern "C" 54 | { 55 | #endif /* __cplusplus */ 56 | 57 | /* If is included, use the C99 complex type. Otherwise 58 | define a type bit-compatible with C99 complex */ 59 | #if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I) 60 | # define FFTW_DEFINE_COMPLEX(R, C) typedef R _Complex C 61 | #else 62 | # define FFTW_DEFINE_COMPLEX(R, C) typedef R C[2] 63 | #endif 64 | 65 | #define FFTW_CONCAT(prefix, name) prefix ## name 66 | #define FFTW_MANGLE_DOUBLE(name) FFTW_CONCAT(fftw_, name) 67 | #define FFTW_MANGLE_FLOAT(name) FFTW_CONCAT(fftwf_, name) 68 | #define FFTW_MANGLE_LONG_DOUBLE(name) FFTW_CONCAT(fftwl_, name) 69 | #define FFTW_MANGLE_QUAD(name) FFTW_CONCAT(fftwq_, name) 70 | 71 | /* IMPORTANT: for Windows compilers, you should add a line 72 | */ 73 | #define FFTW_DLL 74 | /* 75 | here and in kernel/ifftw.h if you are compiling/using FFTW as a 76 | DLL, in order to do the proper importing/exporting, or 77 | alternatively compile with -DFFTW_DLL or the equivalent 78 | command-line flag. This is not necessary under MinGW/Cygwin, where 79 | libtool does the imports/exports automatically. */ 80 | #if defined(FFTW_DLL) && (defined(_WIN32) || defined(__WIN32__)) 81 | /* annoying Windows syntax for shared-library declarations */ 82 | # if defined(COMPILING_FFTW) /* defined in api.h when compiling FFTW */ 83 | # define FFTW_EXTERN extern __declspec(dllexport) 84 | # else /* user is calling FFTW; import symbol */ 85 | # define FFTW_EXTERN extern __declspec(dllimport) 86 | # endif 87 | #else 88 | # define FFTW_EXTERN extern 89 | #endif 90 | 91 | enum fftw_r2r_kind_do_not_use_me { 92 | FFTW_R2HC=0, FFTW_HC2R=1, FFTW_DHT=2, 93 | FFTW_REDFT00=3, FFTW_REDFT01=4, FFTW_REDFT10=5, FFTW_REDFT11=6, 94 | FFTW_RODFT00=7, FFTW_RODFT01=8, FFTW_RODFT10=9, FFTW_RODFT11=10 95 | }; 96 | 97 | struct fftw_iodim_do_not_use_me { 98 | int n; /* dimension size */ 99 | int is; /* input stride */ 100 | int os; /* output stride */ 101 | }; 102 | 103 | #include /* for ptrdiff_t */ 104 | struct fftw_iodim64_do_not_use_me { 105 | ptrdiff_t n; /* dimension size */ 106 | ptrdiff_t is; /* input stride */ 107 | ptrdiff_t os; /* output stride */ 108 | }; 109 | 110 | typedef void (*fftw_write_char_func_do_not_use_me)(char c, void *); 111 | typedef int (*fftw_read_char_func_do_not_use_me)(void *); 112 | 113 | /* 114 | huge second-order macro that defines prototypes for all API 115 | functions. We expand this macro for each supported precision 116 | 117 | X: name-mangling macro 118 | R: real data type 119 | C: complex data type 120 | */ 121 | 122 | #define FFTW_DEFINE_API(X, R, C) \ 123 | \ 124 | FFTW_DEFINE_COMPLEX(R, C); \ 125 | \ 126 | typedef struct X(plan_s) *X(plan); \ 127 | \ 128 | typedef struct fftw_iodim_do_not_use_me X(iodim); \ 129 | typedef struct fftw_iodim64_do_not_use_me X(iodim64); \ 130 | \ 131 | typedef enum fftw_r2r_kind_do_not_use_me X(r2r_kind); \ 132 | \ 133 | typedef fftw_write_char_func_do_not_use_me X(write_char_func); \ 134 | typedef fftw_read_char_func_do_not_use_me X(read_char_func); \ 135 | \ 136 | FFTW_EXTERN void X(execute)(const X(plan) p); \ 137 | \ 138 | FFTW_EXTERN X(plan) X(plan_dft)(int rank, const int *n, \ 139 | C *in, C *out, int sign, unsigned flags); \ 140 | \ 141 | FFTW_EXTERN X(plan) X(plan_dft_1d)(int n, C *in, C *out, int sign, \ 142 | unsigned flags); \ 143 | FFTW_EXTERN X(plan) X(plan_dft_2d)(int n0, int n1, \ 144 | C *in, C *out, int sign, unsigned flags); \ 145 | FFTW_EXTERN X(plan) X(plan_dft_3d)(int n0, int n1, int n2, \ 146 | C *in, C *out, int sign, unsigned flags); \ 147 | \ 148 | FFTW_EXTERN X(plan) X(plan_many_dft)(int rank, const int *n, \ 149 | int howmany, \ 150 | C *in, const int *inembed, \ 151 | int istride, int idist, \ 152 | C *out, const int *onembed, \ 153 | int ostride, int odist, \ 154 | int sign, unsigned flags); \ 155 | \ 156 | FFTW_EXTERN X(plan) X(plan_guru_dft)(int rank, const X(iodim) *dims, \ 157 | int howmany_rank, \ 158 | const X(iodim) *howmany_dims, \ 159 | C *in, C *out, \ 160 | int sign, unsigned flags); \ 161 | FFTW_EXTERN X(plan) X(plan_guru_split_dft)(int rank, const X(iodim) *dims, \ 162 | int howmany_rank, \ 163 | const X(iodim) *howmany_dims, \ 164 | R *ri, R *ii, R *ro, R *io, \ 165 | unsigned flags); \ 166 | \ 167 | FFTW_EXTERN X(plan) X(plan_guru64_dft)(int rank, \ 168 | const X(iodim64) *dims, \ 169 | int howmany_rank, \ 170 | const X(iodim64) *howmany_dims, \ 171 | C *in, C *out, \ 172 | int sign, unsigned flags); \ 173 | FFTW_EXTERN X(plan) X(plan_guru64_split_dft)(int rank, \ 174 | const X(iodim64) *dims, \ 175 | int howmany_rank, \ 176 | const X(iodim64) *howmany_dims, \ 177 | R *ri, R *ii, R *ro, R *io, \ 178 | unsigned flags); \ 179 | \ 180 | FFTW_EXTERN void X(execute_dft)(const X(plan) p, C *in, C *out); \ 181 | FFTW_EXTERN void X(execute_split_dft)(const X(plan) p, R *ri, R *ii, \ 182 | R *ro, R *io); \ 183 | \ 184 | FFTW_EXTERN X(plan) X(plan_many_dft_r2c)(int rank, const int *n, \ 185 | int howmany, \ 186 | R *in, const int *inembed, \ 187 | int istride, int idist, \ 188 | C *out, const int *onembed, \ 189 | int ostride, int odist, \ 190 | unsigned flags); \ 191 | \ 192 | FFTW_EXTERN X(plan) X(plan_dft_r2c)(int rank, const int *n, \ 193 | R *in, C *out, unsigned flags); \ 194 | \ 195 | FFTW_EXTERN X(plan) X(plan_dft_r2c_1d)(int n,R *in,C *out,unsigned flags); \ 196 | FFTW_EXTERN X(plan) X(plan_dft_r2c_2d)(int n0, int n1, \ 197 | R *in, C *out, unsigned flags); \ 198 | FFTW_EXTERN X(plan) X(plan_dft_r2c_3d)(int n0, int n1, \ 199 | int n2, \ 200 | R *in, C *out, unsigned flags); \ 201 | \ 202 | \ 203 | FFTW_EXTERN X(plan) X(plan_many_dft_c2r)(int rank, const int *n, \ 204 | int howmany, \ 205 | C *in, const int *inembed, \ 206 | int istride, int idist, \ 207 | R *out, const int *onembed, \ 208 | int ostride, int odist, \ 209 | unsigned flags); \ 210 | \ 211 | FFTW_EXTERN X(plan) X(plan_dft_c2r)(int rank, const int *n, \ 212 | C *in, R *out, unsigned flags); \ 213 | \ 214 | FFTW_EXTERN X(plan) X(plan_dft_c2r_1d)(int n,C *in,R *out,unsigned flags); \ 215 | FFTW_EXTERN X(plan) X(plan_dft_c2r_2d)(int n0, int n1, \ 216 | C *in, R *out, unsigned flags); \ 217 | FFTW_EXTERN X(plan) X(plan_dft_c2r_3d)(int n0, int n1, \ 218 | int n2, \ 219 | C *in, R *out, unsigned flags); \ 220 | \ 221 | FFTW_EXTERN X(plan) X(plan_guru_dft_r2c)(int rank, const X(iodim) *dims, \ 222 | int howmany_rank, \ 223 | const X(iodim) *howmany_dims, \ 224 | R *in, C *out, \ 225 | unsigned flags); \ 226 | FFTW_EXTERN X(plan) X(plan_guru_dft_c2r)(int rank, const X(iodim) *dims, \ 227 | int howmany_rank, \ 228 | const X(iodim) *howmany_dims, \ 229 | C *in, R *out, \ 230 | unsigned flags); \ 231 | \ 232 | FFTW_EXTERN X(plan) X(plan_guru_split_dft_r2c)( \ 233 | int rank, const X(iodim) *dims, \ 234 | int howmany_rank, \ 235 | const X(iodim) *howmany_dims, \ 236 | R *in, R *ro, R *io, \ 237 | unsigned flags); \ 238 | FFTW_EXTERN X(plan) X(plan_guru_split_dft_c2r)( \ 239 | int rank, const X(iodim) *dims, \ 240 | int howmany_rank, \ 241 | const X(iodim) *howmany_dims, \ 242 | R *ri, R *ii, R *out, \ 243 | unsigned flags); \ 244 | \ 245 | FFTW_EXTERN X(plan) X(plan_guru64_dft_r2c)(int rank, \ 246 | const X(iodim64) *dims, \ 247 | int howmany_rank, \ 248 | const X(iodim64) *howmany_dims, \ 249 | R *in, C *out, \ 250 | unsigned flags); \ 251 | FFTW_EXTERN X(plan) X(plan_guru64_dft_c2r)(int rank, \ 252 | const X(iodim64) *dims, \ 253 | int howmany_rank, \ 254 | const X(iodim64) *howmany_dims, \ 255 | C *in, R *out, \ 256 | unsigned flags); \ 257 | \ 258 | FFTW_EXTERN X(plan) X(plan_guru64_split_dft_r2c)( \ 259 | int rank, const X(iodim64) *dims, \ 260 | int howmany_rank, \ 261 | const X(iodim64) *howmany_dims, \ 262 | R *in, R *ro, R *io, \ 263 | unsigned flags); \ 264 | FFTW_EXTERN X(plan) X(plan_guru64_split_dft_c2r)( \ 265 | int rank, const X(iodim64) *dims, \ 266 | int howmany_rank, \ 267 | const X(iodim64) *howmany_dims, \ 268 | R *ri, R *ii, R *out, \ 269 | unsigned flags); \ 270 | \ 271 | FFTW_EXTERN void X(execute_dft_r2c)(const X(plan) p, R *in, C *out); \ 272 | FFTW_EXTERN void X(execute_dft_c2r)(const X(plan) p, C *in, R *out); \ 273 | \ 274 | FFTW_EXTERN void X(execute_split_dft_r2c)(const X(plan) p, \ 275 | R *in, R *ro, R *io); \ 276 | FFTW_EXTERN void X(execute_split_dft_c2r)(const X(plan) p, \ 277 | R *ri, R *ii, R *out); \ 278 | \ 279 | FFTW_EXTERN X(plan) X(plan_many_r2r)(int rank, const int *n, \ 280 | int howmany, \ 281 | R *in, const int *inembed, \ 282 | int istride, int idist, \ 283 | R *out, const int *onembed, \ 284 | int ostride, int odist, \ 285 | const X(r2r_kind) *kind, unsigned flags); \ 286 | \ 287 | FFTW_EXTERN X(plan) X(plan_r2r)(int rank, const int *n, R *in, R *out, \ 288 | const X(r2r_kind) *kind, unsigned flags); \ 289 | \ 290 | FFTW_EXTERN X(plan) X(plan_r2r_1d)(int n, R *in, R *out, \ 291 | X(r2r_kind) kind, unsigned flags); \ 292 | FFTW_EXTERN X(plan) X(plan_r2r_2d)(int n0, int n1, R *in, R *out, \ 293 | X(r2r_kind) kind0, X(r2r_kind) kind1, \ 294 | unsigned flags); \ 295 | FFTW_EXTERN X(plan) X(plan_r2r_3d)(int n0, int n1, int n2, \ 296 | R *in, R *out, X(r2r_kind) kind0, \ 297 | X(r2r_kind) kind1, X(r2r_kind) kind2, \ 298 | unsigned flags); \ 299 | \ 300 | FFTW_EXTERN X(plan) X(plan_guru_r2r)(int rank, const X(iodim) *dims, \ 301 | int howmany_rank, \ 302 | const X(iodim) *howmany_dims, \ 303 | R *in, R *out, \ 304 | const X(r2r_kind) *kind, unsigned flags); \ 305 | \ 306 | FFTW_EXTERN X(plan) X(plan_guru64_r2r)(int rank, const X(iodim64) *dims, \ 307 | int howmany_rank, \ 308 | const X(iodim64) *howmany_dims, \ 309 | R *in, R *out, \ 310 | const X(r2r_kind) *kind, unsigned flags); \ 311 | \ 312 | FFTW_EXTERN void X(execute_r2r)(const X(plan) p, R *in, R *out); \ 313 | \ 314 | FFTW_EXTERN void X(destroy_plan)(X(plan) p); \ 315 | FFTW_EXTERN void X(forget_wisdom)(void); \ 316 | FFTW_EXTERN void X(cleanup)(void); \ 317 | \ 318 | FFTW_EXTERN void X(set_timelimit)(double t); \ 319 | \ 320 | FFTW_EXTERN void X(plan_with_nthreads)(int nthreads); \ 321 | FFTW_EXTERN int X(init_threads)(void); \ 322 | FFTW_EXTERN void X(cleanup_threads)(void); \ 323 | FFTW_EXTERN void X(make_planner_thread_safe)(void); \ 324 | \ 325 | FFTW_EXTERN int X(export_wisdom_to_filename)(const char *filename); \ 326 | FFTW_EXTERN void X(export_wisdom_to_file)(FILE *output_file); \ 327 | FFTW_EXTERN char *X(export_wisdom_to_string)(void); \ 328 | FFTW_EXTERN void X(export_wisdom)(X(write_char_func) write_char, \ 329 | void *data); \ 330 | FFTW_EXTERN int X(import_system_wisdom)(void); \ 331 | FFTW_EXTERN int X(import_wisdom_from_filename)(const char *filename); \ 332 | FFTW_EXTERN int X(import_wisdom_from_file)(FILE *input_file); \ 333 | FFTW_EXTERN int X(import_wisdom_from_string)(const char *input_string); \ 334 | FFTW_EXTERN int X(import_wisdom)(X(read_char_func) read_char, void *data); \ 335 | \ 336 | FFTW_EXTERN void X(fprint_plan)(const X(plan) p, FILE *output_file); \ 337 | FFTW_EXTERN void X(print_plan)(const X(plan) p); \ 338 | FFTW_EXTERN char *X(sprint_plan)(const X(plan) p); \ 339 | \ 340 | FFTW_EXTERN void *X(malloc)(size_t n); \ 341 | FFTW_EXTERN R *X(alloc_real)(size_t n); \ 342 | FFTW_EXTERN C *X(alloc_complex)(size_t n); \ 343 | FFTW_EXTERN void X(free)(void *p); \ 344 | \ 345 | FFTW_EXTERN void X(flops)(const X(plan) p, \ 346 | double *add, double *mul, double *fmas); \ 347 | FFTW_EXTERN double X(estimate_cost)(const X(plan) p); \ 348 | FFTW_EXTERN double X(cost)(const X(plan) p); \ 349 | \ 350 | FFTW_EXTERN int X(alignment_of)(R *p); \ 351 | FFTW_EXTERN const char X(version)[]; \ 352 | FFTW_EXTERN const char X(cc)[]; \ 353 | FFTW_EXTERN const char X(codelet_optim)[]; 354 | 355 | 356 | /* end of FFTW_DEFINE_API macro */ 357 | 358 | FFTW_DEFINE_API(FFTW_MANGLE_DOUBLE, double, fftw_complex) 359 | FFTW_DEFINE_API(FFTW_MANGLE_FLOAT, float, fftwf_complex) 360 | FFTW_DEFINE_API(FFTW_MANGLE_LONG_DOUBLE, long double, fftwl_complex) 361 | 362 | /* __float128 (quad precision) is a gcc extension on i386, x86_64, and ia64 363 | for gcc >= 4.6 (compiled in FFTW with --enable-quad-precision) */ 364 | #if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) \ 365 | && !(defined(__ICC) || defined(__INTEL_COMPILER) || defined(__CUDACC__) || defined(__PGI)) \ 366 | && (defined(__i386__) || defined(__x86_64__) || defined(__ia64__)) 367 | # if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I) 368 | /* note: __float128 is a typedef, which is not supported with the _Complex 369 | keyword in gcc, so instead we use this ugly __attribute__ version. 370 | However, we can't simply pass the __attribute__ version to 371 | FFTW_DEFINE_API because the __attribute__ confuses gcc in pointer 372 | types. Hence redefining FFTW_DEFINE_COMPLEX. Ugh. */ 373 | # undef FFTW_DEFINE_COMPLEX 374 | # define FFTW_DEFINE_COMPLEX(R, C) typedef _Complex float __attribute__((mode(TC))) C 375 | # endif 376 | FFTW_DEFINE_API(FFTW_MANGLE_QUAD, __float128, fftwq_complex) 377 | #endif 378 | 379 | #define FFTW_FORWARD (-1) 380 | #define FFTW_BACKWARD (+1) 381 | 382 | #define FFTW_NO_TIMELIMIT (-1.0) 383 | 384 | /* documented flags */ 385 | #define FFTW_MEASURE (0U) 386 | #define FFTW_DESTROY_INPUT (1U << 0) 387 | #define FFTW_UNALIGNED (1U << 1) 388 | #define FFTW_CONSERVE_MEMORY (1U << 2) 389 | #define FFTW_EXHAUSTIVE (1U << 3) /* NO_EXHAUSTIVE is default */ 390 | #define FFTW_PRESERVE_INPUT (1U << 4) /* cancels FFTW_DESTROY_INPUT */ 391 | #define FFTW_PATIENT (1U << 5) /* IMPATIENT is default */ 392 | #define FFTW_ESTIMATE (1U << 6) 393 | #define FFTW_WISDOM_ONLY (1U << 21) 394 | 395 | /* undocumented beyond-guru flags */ 396 | #define FFTW_ESTIMATE_PATIENT (1U << 7) 397 | #define FFTW_BELIEVE_PCOST (1U << 8) 398 | #define FFTW_NO_DFT_R2HC (1U << 9) 399 | #define FFTW_NO_NONTHREADED (1U << 10) 400 | #define FFTW_NO_BUFFERING (1U << 11) 401 | #define FFTW_NO_INDIRECT_OP (1U << 12) 402 | #define FFTW_ALLOW_LARGE_GENERIC (1U << 13) /* NO_LARGE_GENERIC is default */ 403 | #define FFTW_NO_RANK_SPLITS (1U << 14) 404 | #define FFTW_NO_VRANK_SPLITS (1U << 15) 405 | #define FFTW_NO_VRECURSE (1U << 16) 406 | #define FFTW_NO_SIMD (1U << 17) 407 | #define FFTW_NO_SLOW (1U << 18) 408 | #define FFTW_NO_FIXED_RADIX_LARGE_N (1U << 19) 409 | #define FFTW_ALLOW_PRUNING (1U << 20) 410 | 411 | #ifdef __cplusplus 412 | } /* extern "C" */ 413 | #endif /* __cplusplus */ 414 | 415 | #endif /* FFTW3_H */ 416 | -------------------------------------------------------------------------------- /src/winlibs/mman.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | #include "mman.h" 7 | 8 | #ifndef FILE_MAP_EXECUTE 9 | #define FILE_MAP_EXECUTE 0x0020 10 | #endif /* FILE_MAP_EXECUTE */ 11 | 12 | static int __map_mman_error(const DWORD err, const int deferr) 13 | { 14 | if (err == 0) 15 | return 0; 16 | //TODO: implement 17 | return err; 18 | } 19 | 20 | static DWORD __map_mmap_prot_page(const int prot) 21 | { 22 | DWORD protect = 0; 23 | 24 | if (prot == PROT_NONE) 25 | return protect; 26 | 27 | if ((prot & PROT_EXEC) != 0) 28 | { 29 | protect = ((prot & PROT_WRITE) != 0) ? 30 | PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; 31 | } 32 | else 33 | { 34 | protect = ((prot & PROT_WRITE) != 0) ? 35 | PAGE_READWRITE : PAGE_READONLY; 36 | } 37 | 38 | return protect; 39 | } 40 | 41 | static DWORD __map_mmap_prot_file(const int prot) 42 | { 43 | DWORD desiredAccess = 0; 44 | 45 | if (prot == PROT_NONE) 46 | return desiredAccess; 47 | 48 | if ((prot & PROT_READ) != 0) 49 | desiredAccess |= FILE_MAP_READ; 50 | if ((prot & PROT_WRITE) != 0) 51 | desiredAccess |= FILE_MAP_WRITE; 52 | if ((prot & PROT_EXEC) != 0) 53 | desiredAccess |= FILE_MAP_EXECUTE; 54 | 55 | return desiredAccess; 56 | } 57 | 58 | void* mmap(void *addr, size_t len, int prot, int flags, int fildes, OffsetType off) 59 | { 60 | HANDLE fm, h; 61 | 62 | void * map = MAP_FAILED; 63 | 64 | #ifdef _MSC_VER 65 | #pragma warning(push) 66 | #pragma warning(disable: 4293) 67 | #endif 68 | 69 | const DWORD dwFileOffsetLow = (sizeof(OffsetType) <= sizeof(DWORD)) ? 70 | (DWORD)off : (DWORD)(off & 0xFFFFFFFFL); 71 | const DWORD dwFileOffsetHigh = (sizeof(OffsetType) <= sizeof(DWORD)) ? 72 | (DWORD)0 : (DWORD)((off >> 32) & 0xFFFFFFFFL); 73 | const DWORD protect = __map_mmap_prot_page(prot); 74 | const DWORD desiredAccess = __map_mmap_prot_file(prot); 75 | 76 | const OffsetType maxSize = off + (OffsetType)len; 77 | 78 | const DWORD dwMaxSizeLow = (sizeof(OffsetType) <= sizeof(DWORD)) ? 79 | (DWORD)maxSize : (DWORD)(maxSize & 0xFFFFFFFFL); 80 | const DWORD dwMaxSizeHigh = (sizeof(OffsetType) <= sizeof(DWORD)) ? 81 | (DWORD)0 : (DWORD)((maxSize >> 32) & 0xFFFFFFFFL); 82 | 83 | #ifdef _MSC_VER 84 | #pragma warning(pop) 85 | #endif 86 | 87 | errno = 0; 88 | 89 | if (len == 0 90 | /* Unsupported flag combinations */ 91 | || (flags & MAP_FIXED) != 0 92 | /* Usupported protection combinations */ 93 | || prot == PROT_EXEC) 94 | { 95 | errno = EINVAL; 96 | return MAP_FAILED; 97 | } 98 | 99 | h = ((flags & MAP_ANONYMOUS) == 0) ? 100 | (HANDLE)_get_osfhandle(fildes) : INVALID_HANDLE_VALUE; 101 | 102 | if ((flags & MAP_ANONYMOUS) == 0 && h == INVALID_HANDLE_VALUE) 103 | { 104 | errno = EBADF; 105 | return MAP_FAILED; 106 | } 107 | 108 | fm = CreateFileMapping(h, NULL, protect, dwMaxSizeHigh, dwMaxSizeLow, NULL); 109 | 110 | if (fm == NULL) 111 | { 112 | errno = __map_mman_error(GetLastError(), EPERM); 113 | return MAP_FAILED; 114 | } 115 | 116 | map = MapViewOfFile(fm, desiredAccess, dwFileOffsetHigh, dwFileOffsetLow, len); 117 | 118 | CloseHandle(fm); 119 | 120 | if (map == NULL) 121 | { 122 | errno = __map_mman_error(GetLastError(), EPERM); 123 | return MAP_FAILED; 124 | } 125 | 126 | return map; 127 | } 128 | 129 | int munmap(void *addr, size_t len) 130 | { 131 | if (UnmapViewOfFile(addr)) 132 | return 0; 133 | 134 | errno = __map_mman_error(GetLastError(), EPERM); 135 | 136 | return -1; 137 | } 138 | 139 | int _mprotect(void *addr, size_t len, int prot) 140 | { 141 | DWORD newProtect = __map_mmap_prot_page(prot); 142 | DWORD oldProtect = 0; 143 | 144 | if (VirtualProtect(addr, len, newProtect, &oldProtect)) 145 | return 0; 146 | 147 | errno = __map_mman_error(GetLastError(), EPERM); 148 | 149 | return -1; 150 | } 151 | 152 | int msync(void *addr, size_t len, int flags) 153 | { 154 | if (FlushViewOfFile(addr, len)) 155 | return 0; 156 | 157 | errno = __map_mman_error(GetLastError(), EPERM); 158 | 159 | return -1; 160 | } 161 | 162 | int mlock(const void *addr, size_t len) 163 | { 164 | if (VirtualLock((LPVOID)addr, len)) 165 | return 0; 166 | 167 | errno = __map_mman_error(GetLastError(), EPERM); 168 | 169 | return -1; 170 | } 171 | 172 | int munlock(const void *addr, size_t len) 173 | { 174 | if (VirtualUnlock((LPVOID)addr, len)) 175 | return 0; 176 | 177 | errno = __map_mman_error(GetLastError(), EPERM); 178 | 179 | return -1; 180 | } 181 | #if !defined(__MINGW32__) 182 | int ftruncate(int fd, unsigned int size) { 183 | if (fd < 0) { 184 | errno = EBADF; 185 | return -1; 186 | } 187 | 188 | HANDLE h = (HANDLE)_get_osfhandle(fd); 189 | unsigned int cur = SetFilePointer(h, 0, NULL, FILE_CURRENT); 190 | if (cur == ~0 || SetFilePointer(h, size, NULL, FILE_BEGIN) == ~0 || !SetEndOfFile(h)) { 191 | int error = GetLastError(); 192 | switch (GetLastError()) { 193 | case ERROR_INVALID_HANDLE: 194 | errno = EBADF; 195 | break; 196 | default: 197 | errno = EIO; 198 | break; 199 | } 200 | return -1; 201 | } 202 | 203 | return 0; 204 | } 205 | #endif -------------------------------------------------------------------------------- /src/winlibs/mman.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sys/mman.h 3 | * mman-win32 4 | */ 5 | 6 | #ifndef _SYS_MMAN_H_ 7 | #define _SYS_MMAN_H_ 8 | 9 | #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. 10 | #define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. 11 | #endif 12 | 13 | /* All the headers include this file. */ 14 | #ifndef _MSC_VER 15 | #include <_mingw.h> 16 | #endif 17 | 18 | #if defined(MMAN_LIBRARY_DLL) 19 | /* Windows shared libraries (DLL) must be declared export when building the lib and import when building the 20 | application which links against the library. */ 21 | #if defined(MMAN_LIBRARY) 22 | #define MMANSHARED_EXPORT __declspec(dllexport) 23 | #else 24 | #define MMANSHARED_EXPORT __declspec(dllimport) 25 | #endif /* MMAN_LIBRARY */ 26 | #else 27 | /* Static libraries do not require a __declspec attribute.*/ 28 | #define MMANSHARED_EXPORT 29 | #endif /* MMAN_LIBRARY_DLL */ 30 | 31 | /* Determine offset type */ 32 | #include 33 | #if defined(_WIN64) 34 | typedef int64_t OffsetType; 35 | #else 36 | typedef uint32_t OffsetType; 37 | #endif 38 | 39 | #include 40 | 41 | #ifdef __cplusplus 42 | extern "C" { 43 | #endif 44 | 45 | #define PROT_NONE 0 46 | #define PROT_READ 1 47 | #define PROT_WRITE 2 48 | #define PROT_EXEC 4 49 | 50 | #define MAP_FILE 0 51 | #define MAP_SHARED 1 52 | #define MAP_PRIVATE 2 53 | #define MAP_TYPE 0xf 54 | #define MAP_FIXED 0x10 55 | #define MAP_ANONYMOUS 0x20 56 | #define MAP_ANON MAP_ANONYMOUS 57 | 58 | #define MAP_FAILED ((void *)-1) 59 | 60 | /* Flags for msync. */ 61 | #define MS_ASYNC 1 62 | #define MS_SYNC 2 63 | #define MS_INVALIDATE 4 64 | 65 | MMANSHARED_EXPORT void* mmap(void *addr, size_t len, int prot, int flags, int fildes, OffsetType off); 66 | MMANSHARED_EXPORT int munmap(void *addr, size_t len); 67 | MMANSHARED_EXPORT int _mprotect(void *addr, size_t len, int prot); 68 | MMANSHARED_EXPORT int msync(void *addr, size_t len, int flags); 69 | MMANSHARED_EXPORT int mlock(const void *addr, size_t len); 70 | MMANSHARED_EXPORT int munlock(const void *addr, size_t len); 71 | #if !defined(__MINGW32__) 72 | MMANSHARED_EXPORT int ftruncate(int fd, unsigned int size); 73 | #endif 74 | #ifdef __cplusplus 75 | } 76 | #endif 77 | 78 | 79 | 80 | 81 | 82 | #endif /* _SYS_MMAN_H_ */ 83 | -------------------------------------------------------------------------------- /src/winlibs/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // FItSNE.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /src/winlibs/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #ifdef _WIN32 9 | 10 | #define _CRT_SECURE_NO_WARNINGS 11 | #define _CRT_SECURE_NO_DEPRECATE 12 | 13 | #include "targetver.h" 14 | 15 | #include 16 | #include 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /src/winlibs/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /src/winlibs/unistd.h: -------------------------------------------------------------------------------- 1 | #ifndef _UNISTD_H 2 | #define _UNISTD_H 1 3 | 4 | /* This is intended as a drop-in replacement for unistd.h on Windows. 5 | * Please add functionality as neeeded. 6 | * https://stackoverflow.com/a/826027/1202830 7 | */ 8 | 9 | #include 10 | #include 11 | //#include /* getopt at: https://gist.github.com/ashelly/7776712 */ 12 | #include /* for getpid() and the exec..() family */ 13 | #include /* for _getcwd() and _chdir() */ 14 | 15 | #define srandom srand 16 | #define random rand 17 | 18 | /* Values for the second argument to access. 19 | These may be OR'd together. */ 20 | #define R_OK 4 /* Test for read permission. */ 21 | #define W_OK 2 /* Test for write permission. */ 22 | //#define X_OK 1 /* execute permission - unsupported in windows*/ 23 | #define F_OK 0 /* Test for existence. */ 24 | 25 | #define access _access 26 | #define dup2 _dup2 27 | #define execve _execve 28 | #define ftruncate _chsize 29 | #define unlink _unlink 30 | #define fileno _fileno 31 | #define getcwd _getcwd 32 | #define chdir _chdir 33 | #define isatty _isatty 34 | #define lseek _lseek 35 | /* read, write, and close are NOT being #defined here, because while there are file handle specific versions for Windows, they probably don't work for sockets. You need to look at your app and consider whether to call e.g. closesocket(). */ 36 | 37 | #ifdef _WIN64 38 | #define ssize_t __int64 39 | #else 40 | #define ssize_t long 41 | #endif 42 | 43 | #define STDIN_FILENO 0 44 | #define STDOUT_FILENO 1 45 | #define STDERR_FILENO 2 46 | /* should be in some equivalent to */ 47 | //typedef __int8 int8_t; 48 | //typedef __int16 int16_t; 49 | //typedef __int32 int32_t; 50 | //typedef __int64 int64_t; 51 | //typedef unsigned __int8 uint8_t; 52 | //typedef unsigned __int16 uint16_t; 53 | //typedef unsigned __int32 uint32_t; 54 | //typedef unsigned __int64 uint64_t; 55 | 56 | #endif /* unistd.h */ --------------------------------------------------------------------------------