Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /******/ (function(modules) { // webpackBootstrap
- /******/ // The module cache
- /******/ var installedModules = {};
- /******/
- /******/ // The require function
- /******/ function __webpack_require__(moduleId) {
- /******/
- /******/ // Check if module is in cache
- /******/ if(installedModules[moduleId]) {
- /******/ return installedModules[moduleId].exports;
- /******/ }
- /******/ // Create a new module (and put it into the cache)
- /******/ var module = installedModules[moduleId] = {
- /******/ i: moduleId,
- /******/ l: false,
- /******/ exports: {}
- /******/ };
- /******/
- /******/ // Execute the module function
- /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
- /******/
- /******/ // Flag the module as loaded
- /******/ module.l = true;
- /******/
- /******/ // Return the exports of the module
- /******/ return module.exports;
- /******/ }
- /******/
- /******/
- /******/ // expose the modules object (__webpack_modules__)
- /******/ __webpack_require__.m = modules;
- /******/
- /******/ // expose the module cache
- /******/ __webpack_require__.c = installedModules;
- /******/
- /******/ // identity function for calling harmony imports with the correct context
- /******/ __webpack_require__.i = function(value) { return value; };
- /******/
- /******/ // define getter function for harmony exports
- /******/ __webpack_require__.d = function(exports, name, getter) {
- /******/ if(!__webpack_require__.o(exports, name)) {
- /******/ Object.defineProperty(exports, name, {
- /******/ configurable: false,
- /******/ enumerable: true,
- /******/ get: getter
- /******/ });
- /******/ }
- /******/ };
- /******/
- /******/ // getDefaultExport function for compatibility with non-harmony modules
- /******/ __webpack_require__.n = function(module) {
- /******/ var getter = module && module.__esModule ?
- /******/ function getDefault() { return module['default']; } :
- /******/ function getModuleExports() { return module; };
- /******/ __webpack_require__.d(getter, 'a', getter);
- /******/ return getter;
- /******/ };
- /******/
- /******/ // Object.prototype.hasOwnProperty.call
- /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
- /******/
- /******/ // __webpack_public_path__
- /******/ __webpack_require__.p = "";
- /******/
- /******/ // Load entry module and return exports
- /******/ return __webpack_require__(__webpack_require__.s = 2);
- /******/ })
- /************************************************************************/
- /******/ ([
- /* 0 */
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- class ComplexArray {
- constructor(other, arrayType = Float32Array) {
- if (other instanceof ComplexArray) {
- // Copy constuctor.
- this.ArrayType = other.ArrayType;
- this.real = new this.ArrayType(other.real);
- this.imag = new this.ArrayType(other.imag);
- } else {
- this.ArrayType = arrayType;
- // other can be either an array or a number.
- this.real = new this.ArrayType(other);
- this.imag = new this.ArrayType(this.real.length);
- }
- this.length = this.real.length;
- }
- toString() {
- const components = [];
- this.forEach((value, i) => {
- components.push(
- `(${value.real.toFixed(2)}, ${value.imag.toFixed(2)})`
- );
- });
- return `[${components.join(', ')}]`;
- }
- forEach(iterator) {
- const n = this.length;
- // For gc efficiency, re-use a single object in the iterator.
- const value = Object.seal(Object.defineProperties({}, {
- real: {writable: true}, imag: {writable: true},
- }));
- for (let i = 0; i < n; i++) {
- value.real = this.real[i];
- value.imag = this.imag[i];
- iterator(value, i, n);
- }
- }
- // In-place mapper.
- map(mapper) {
- this.forEach((value, i, n) => {
- mapper(value, i, n);
- this.real[i] = value.real;
- this.imag[i] = value.imag;
- });
- return this;
- }
- conjugate() {
- return new ComplexArray(this).map((value) => {
- value.imag *= -1;
- });
- }
- magnitude() {
- const mags = new this.ArrayType(this.length);
- this.forEach((value, i) => {
- mags[i] = Math.sqrt(value.real*value.real + value.imag*value.imag);
- })
- return mags;
- }
- }
- /* harmony export (immutable) */ __webpack_exports__["a"] = ComplexArray;
- /***/ }),
- /* 1 */
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
- "use strict";
- /* unused harmony export FFT */
- /* unused harmony export InvFFT */
- /* unused harmony export frequencyMap */
- /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__complex_array__ = __webpack_require__(0);
- // Math constants and functions we need.
- const PI = Math.PI;
- const SQRT1_2 = Math.SQRT1_2;
- function FFT(input) {
- return ensureComplexArray(input).FFT();
- };
- function InvFFT(input) {
- return ensureComplexArray(input).InvFFT();
- };
- function frequencyMap(input, filterer) {
- return ensureComplexArray(input).frequencyMap(filterer);
- };
- class ComplexArray extends __WEBPACK_IMPORTED_MODULE_0__complex_array__["a" /* default */] {
- FFT() {
- return fft(this, false);
- }
- InvFFT() {
- return fft(this, true);
- }
- FFT_mult(that) {
- // Complexity: O(n * log(n))
- const n = this.length;
- fft(this, false);
- fft(that, false); // discarded
- for (let i = 0; i < n; i++) {
- // pointwise multiplication
- let real = this.real[i] * that.real[i] - this.imag[i] * that.imag[i];
- let imag = this.real[i] * that.imag[i] + this.imag[i] * that.real[i];
- this.real[i] = real;
- this.imag[i] = imag;
- }
- return fft(this, true);
- }
- FFT_sq() {
- // Complexity: O(n * log(n))
- const n = this.length;
- fft(this, false);
- for (let i = 0; i < n; i++) {
- // pointwise multiplication
- let real = this.real[i] * this.real[i] - this.imag[i] * this.imag[i];
- let imag = 2 * this.real[i] * this.imag[i];
- this.real[i] = real;
- this.imag[i] = imag;
- }
- return fft(this, true);
- }
- FFT_recip() {
- // y *= (2 - x * y)
- // Complexity: O(n * log(n)^2)
- const n = this.length;
- const m = 2 * n;
- let out = new ComplexArray(m);
- let a = new ComplexArray(m);
- let b = new ComplexArray(m);
- let x = 1 / (this.real[0] ** 2 + this.imag[0] ** 2);
- let prec = 1;
- out.real[0] = this.real[0] * x;
- out.imag[0] = -this.imag[0] * x;
- do
- {
- for (let i = 0; i < n; i++) {
- a.real[i] = out.real[i];
- a.imag[i] = out.imag[i];
- b.real[i] = this.real[i];
- b.imag[i] = this.imag[i];
- }
- a.FFT_mult(b);
- a.real[0] = 2 - a.real[0];
- a.imag[0] = a.imag[0];
- for (let i = 1; i < n; i++) {
- a.real[i] = -a.real[i];
- a.imag[i] = -a.imag[i];
- }
- for (let i = n; i < m; i++) {
- a.real[i] = 0;
- a.imag[i] = 0;
- b.real[i] = 0;
- b.imag[i] = 0;
- }
- out.FFT_mult(a);
- for (let i = n; i < m; i++) {
- a.real[i] = 0;
- a.imag[i] = 0;
- out.real[i] = 0;
- out.imag[i] = 0;
- }
- prec *= 2;
- }
- while (prec < n);
- for (let i = 0; i < n; i++) {
- this.real[i] = out.real[i];
- this.imag[i] = out.imag[i];
- }
- }
- // Applies a frequency-space filter to input, and returns the real-space
- // filtered input.
- // filterer accepts freq, i, n and modifies freq.real and freq.imag.
- frequencyMap(filterer) {
- return this.FFT().map(filterer).InvFFT();
- }
- }
- /* harmony export (immutable) */ __webpack_exports__["a"] = ComplexArray;
- function ensureComplexArray(input) {
- return input instanceof ComplexArray && input || new ComplexArray(input);
- }
- function fft(input, inverse) {
- const n = input.length;
- if (n & (n - 1)) {
- return FFT_Recursive(input, inverse);
- } else {
- return FFT_2_Iterative(input, inverse);
- }
- }
- function FFT_Recursive(input, inverse) {
- const n = input.length;
- if (n === 1) {
- return input;
- }
- const output = new ComplexArray(n, input.ArrayType);
- // Use the lowest odd factor, so we are able to use FFT_2_Iterative in the
- // recursive transforms optimally.
- const p = LowestOddFactor(n);
- const m = n / p;
- const factor = inverse ? 1 / p : 1;
- let recursive_result = new ComplexArray(m, input.ArrayType);
- // Loops go like O(n Σ p_i), where p_i are the prime factors of n.
- // for a power of a prime, p, this reduces to O(n p log_p n)
- for(let j = 0; j < p; j++) {
- for(let i = 0; i < m; i++) {
- recursive_result.real[i] = input.real[i * p + j];
- recursive_result.imag[i] = input.imag[i * p + j];
- }
- // Don't go deeper unless necessary to save allocs.
- if (m > 1) {
- recursive_result = fft(recursive_result, inverse);
- }
- const del_f_r = Math.cos(2*PI*j/n);
- const del_f_i = (inverse ? -1 : 1) * Math.sin(2*PI*j/n);
- let f_r = 1;
- let f_i = 0;
- for(let i = 0; i < n; i++) {
- const _real = recursive_result.real[i % m];
- const _imag = recursive_result.imag[i % m];
- output.real[i] += f_r * _real - f_i * _imag;
- output.imag[i] += f_r * _imag + f_i * _real;
- [f_r, f_i] = [
- f_r * del_f_r - f_i * del_f_i,
- f_i = f_r * del_f_i + f_i * del_f_r,
- ];
- }
- }
- // Copy back to input to match FFT_2_Iterative in-placeness
- // TODO: faster way of making this in-place?
- for(let i = 0; i < n; i++) {
- input.real[i] = factor * output.real[i];
- input.imag[i] = factor * output.imag[i];
- }
- return input;
- }
- function FFT_2_Iterative(input, inverse) {
- const n = input.length;
- const output = BitReverseComplexArray(input);
- const output_r = output.real;
- const output_i = output.imag;
- // Loops go like O(n log n):
- // width ~ log n; i,j ~ n
- let width = 1, factor = inverse ? 0.5 : 1;
- while (width < n) {
- const del_f_r = Math.cos(PI/width);
- const del_f_i = (inverse ? -1 : 1) * Math.sin(PI/width);
- for (let i = 0; i < n/(2*width); i++) {
- let f_r = 1;
- let f_i = 0;
- for (let j = 0; j < width; j++) {
- const l_index = 2*i*width + j;
- const r_index = l_index + width;
- const left_r = output_r[l_index];
- const left_i = output_i[l_index];
- const right_r = f_r * output_r[r_index] - f_i * output_i[r_index];
- const right_i = f_i * output_r[r_index] + f_r * output_i[r_index];
- output_r[l_index] = factor * (left_r + right_r);
- output_i[l_index] = factor * (left_i + right_i);
- output_r[r_index] = factor * (left_r - right_r);
- output_i[r_index] = factor * (left_i - right_i);
- [f_r, f_i] = [
- f_r * del_f_r - f_i * del_f_i,
- f_r * del_f_i + f_i * del_f_r,
- ];
- }
- }
- width <<= 1;
- }
- return output;
- }
- function BitReverseIndex(index, n) {
- let bitreversed_index = 0;
- while (n > 1) {
- bitreversed_index <<= 1;
- bitreversed_index += index & 1;
- index >>= 1;
- n >>= 1;
- }
- return bitreversed_index;
- }
- function BitReverseComplexArray(array) {
- const n = array.length;
- const flips = new Set();
- for(let i = 0; i < n; i++) {
- const r_i = BitReverseIndex(i, n);
- if (flips.has(i)) continue;
- [array.real[i], array.real[r_i]] = [array.real[r_i], array.real[i]];
- [array.imag[i], array.imag[r_i]] = [array.imag[r_i], array.imag[i]];
- flips.add(r_i);
- }
- return array;
- }
- function LowestOddFactor(n) {
- const sqrt_n = Math.sqrt(n);
- let factor = 3;
- while(factor <= sqrt_n) {
- if (n % factor === 0) return factor;
- factor += 2;
- }
- return n;
- }
- /***/ }),
- /* 2 */
- /***/ (function(module, exports, __webpack_require__) {
- module.exports = __webpack_require__(1);
- window.FFT_polynomial = module.exports["a" /* ComplexArray */];
- /***/ })
- /******/ ]);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement