diff options
author | Android Chromium Automerger <chromium-automerger@android> | 2014-06-20 13:33:50 +0000 |
---|---|---|
committer | Android Chromium Automerger <chromium-automerger@android> | 2014-06-20 13:33:50 +0000 |
commit | 1aca6aca2ce52791824da4a7d1560b4da3e137f2 (patch) | |
tree | 47f2cedf1ab09a13880766f4e5d08bdae3e189af | |
parent | 40230117fae2a85e6dfd29ff181ca6d7b6d197c3 (diff) | |
parent | 333c00b74820c9dc0022d124c5a10a788d74d5ca (diff) | |
download | openmax_dl-1aca6aca2ce52791824da4a7d1560b4da3e137f2.tar.gz |
Merge third_party/openmax_dl from https://chromium.googlesource.com/external/webrtc/deps/third_party/openmax.git at 333c00b74820c9dc0022d124c5a10a788d74d5ca
This commit was generated by merge_from_chromium.py.
Change-Id: I7af29450ea74a0468e586a622c8403ee03b3b610
38 files changed, 7354 insertions, 317 deletions
diff --git a/dl/api/arm/arm64COMM_s.h b/dl/api/arm/arm64COMM_s.h new file mode 100644 index 0000000..e19ceee --- /dev/null +++ b/dl/api/arm/arm64COMM_s.h @@ -0,0 +1,258 @@ +// -*- Mode: asm; -*- +// +// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// This file was originally licensed as follows. It has been +// relicensed with permission from the copyright holders. +// + +// +// File Name: armCOMM_s.h +// OpenMAX DL: v1.0.2 +// Last Modified Revision: 13871 +// Last Modified Date: Fri, 09 May 2008 +// +// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. +// +// +// +// ARM optimized OpenMAX common header file +// + + .set _SBytes, 0 // Number of scratch bytes on stack + .set _Workspace, 0 // Stack offset of scratch workspace + + .set _RRegList, 0 // R saved register list (last register number) + .set _DRegList, 0 // D saved register list (last register number) + + // Work out list of D saved registers, like for R registers. + .macro _M_GETDREGLIST dreg + .ifeqs "\dreg", "" + .set _DRegList, 0 + .exitm + .endif + + .ifeqs "\dreg", "d8" + .set _DRegList, 8 + .exitm + .endif + + .ifeqs "\dreg", "d9" + .set _DRegList, 9 + .exitm + .endif + + .ifeqs "\dreg", "d10" + .set _DRegList, 10 + .exitm + .endif + + .ifeqs "\dreg", "d11" + .set _DRegList, 11 + .exitm + .endif + + .ifeqs "\dreg", "d12" + .set _DRegList, 12 + .exitm + .endif + + .ifeqs "\dreg", "d13" + .set _DRegList, 13 + .exitm + .endif + + .ifeqs "\dreg", "d14" + .set _DRegList, 14 + .exitm + .endif + + .ifeqs "\dreg", "d15" + .set _DRegList, 15 + .exitm + .endif + + .warning "Unrecognized saved d register limit: \rreg" + .endm + +////////////////////////////////////////////////////////// +// Function header and footer macros +////////////////////////////////////////////////////////// + + // Function Header Macro + // Generates the function prologue + // Note that functions should all be "stack-moves-once" + // The FNSTART and FNEND macros should be the only places + // where the stack moves. + // + // name = function name + // rreg = "" don't stack any registers + // "lr" stack "lr" only + // "rN" stack registers "r4-rN,lr" + // dreg = "" don't stack any D registers + // "dN" stack registers "d8-dN" + // + // Note: ARM Archicture procedure call standard AAPCS + // states that r4-r11, sp, d8-d15 must be preserved by + // a compliant function. + .macro M_START name, rreg, dreg + .set _Workspace, 0 + + // Define the function and make it external. + .global \name + .func \name + .section .text.\name,"ax",%progbits + .align 4 +\name : +//.fnstart + // Save specified R registers + _M_PUSH_RREG + + // Save specified D registers + _M_GETDREGLIST \dreg + _M_PUSH_DREG + + // Ensure size claimed on stack is 16-byte aligned for ARM64 + .if (_SBytes & 15) != 0 + .set _SBytes, _SBytes + (16 - (_SBytes & 15)) + .endif + .if _SBytes != 0 + sub sp, sp, #_SBytes + .endif + .endm + + // Function Footer Macro + // Generates the function epilogue + .macro M_END + // Restore the stack pointer to its original value on function entry + .if _SBytes != 0 + add sp, sp, #_SBytes + .endif + // Restore any saved R or D registers. + _M_RET + //.fnend + .endfunc + // Reset the global stack tracking variables back to their + // initial values. + .set _SBytes, 0 + .endm + + // Based on the value of _DRegList, push the specified set of registers + // to the stack. + // The ARM64 ABI says only v8-v15 needs to be saved across calls and only + // the lower 64 bits need to be saved. + .macro _M_PUSH_DREG + .if _DRegList >= 8 + sub sp, sp, (_DRegList - 7) * 16 // 16-byte alignment + str q8, [sp] + .endif + + .if _DRegList >= 9 + str q9, [sp, #16] + .endif + + .if _DRegList >= 10 + str q10, [sp, #32] + .endif + + .if _DRegList >= 11 + str q11, [sp, #48] + .endif + + .if _DRegList >= 12 + str q12, [sp, #64] + .endif + + .if _DRegList >= 13 + str q13, [sp, #80] + .endif + + .if _DRegList >= 14 + str q14, [sp, #96] + .endif + + .if _DRegList >= 15 + str q15, [sp, #112] + .endif + + .exitm + .endm + + // Based on the value of _RRegList, push the specified set of registers + // to the stack. + // The ARM64 ABI says registers r19-r29 needs to be saved across calls. + // But for the FFT routines, we don't need to save anything, so just + // preserve the SP and LR. + .macro _M_PUSH_RREG + sub sp, sp, #16 + str x30, [sp] + str x29, [sp, #8] + .exitm + .endm + + // The opposite of _M_PUSH_DREG + .macro _M_POP_DREG + .if _DRegList >= 8 + ldr q8, [sp] + .endif + + .if _DRegList >= 9 + ldr q9, [sp, #16] + .endif + + .if _DRegList >= 10 + ldr q10, [sp, #32] + .endif + + .if _DRegList >= 11 + ldr q11, [sp, #48] + .endif + + .if _DRegList >= 12 + ldr q12, [sp, #64] + .endif + + .if _DRegList >= 13 + ldr q13, [sp, #80] + .endif + + .if _DRegList >= 14 + ldr q14, [sp, #96] + .endif + + .if _DRegList >= 15 + ldr q15, [sp, #112] + .endif + + .if _DRegList >= 8 + add sp, sp, (_DRegList - 7) * 16 // 16-byte alignment + .endif + .exitm + .endm + + // The opposite of _M_PUSH_RREG + .macro _M_POP_RREG cc + ldr x29, [sp, #8] + ldr x30, [sp] + add sp, sp, #16 + .exitm + .endm + + // Produce function return instructions + .macro _M_RET cc + _M_POP_DREG \cc + _M_POP_RREG \cc + ret + .endm + // rsb - reverse subtract + // compute dst = src2 - src1, useful when src2 is an immediate value + .macro rsb dst, src1, src2 + sub \dst, \src1, \src2 + neg \dst, \dst + .endm diff --git a/dl/api/arm/armCOMM_s.h b/dl/api/arm/armCOMM_s.h index 6ce1e2f..f9645dd 100644 --- a/dl/api/arm/armCOMM_s.h +++ b/dl/api/arm/armCOMM_s.h @@ -167,6 +167,7 @@ .set _Workspace, 0 @ Define the function and make it external. + .arm .global \name .func \name .section .text.\name,"ax",%progbits diff --git a/dl/api/arm/omxtypes_s.h b/dl/api/arm/omxtypes_s.h index d880d35..b27f72d 100644 --- a/dl/api/arm/omxtypes_s.h +++ b/dl/api/arm/omxtypes_s.h @@ -1,76 +1,76 @@ -@// -@// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. -@// -@// Use of this source code is governed by a BSD-style license -@// that can be found in the LICENSE file in the root of the source -@// tree. An additional intellectual property rights grant can be found -@// in the file PATENTS. All contributing project authors may -@// be found in the AUTHORS file in the root of the source tree. -@// -@// This file was originally licensed as follows. It has been -@// relicensed with permission from the copyright holders. -@// +// +// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// This file was originally licensed as follows. It has been +// relicensed with permission from the copyright holders. +// -@// -@// File Name: omxtypes_s.h -@// OpenMAX DL: v1.0.2 -@// Last Modified Revision: 9622 -@// Last Modified Date: Wed, 06 Feb 2008 -@// -@// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. -@// -@// +// +// File Name: omxtypes_s.h +// OpenMAX DL: v1.0.2 +// Last Modified Revision: 9622 +// Last Modified Date: Wed, 06 Feb 2008 +// +// (c) Copyright 2007-2008 ARM Limited. All Rights Reserved. +// +// -@// Mandatory return codes - use cases are explicitly described for each function - .equ OMX_Sts_NoErr, 0 @// No error the function completed successfully - .equ OMX_Sts_Err, -2 @// Unknown/unspecified error - .equ OMX_Sts_InvalidBitstreamValErr, -182 @// Invalid value detected during bitstream processing - .equ OMX_Sts_MemAllocErr, -9 @// Not enough memory allocated for the operation - .equ OMX_StsACAAC_GainCtrErr, -159 @// AAC: Unsupported gain control data detected - .equ OMX_StsACAAC_PrgNumErr, -167 @// AAC: Invalid number of elements for one program - .equ OMX_StsACAAC_CoefValErr, -163 @// AAC: Invalid quantized coefficient value - .equ OMX_StsACAAC_MaxSfbErr, -162 @// AAC: Invalid maxSfb value in relation to numSwb - .equ OMX_StsACAAC_PlsDataErr, -160 @// AAC: pulse escape sequence data error +// Mandatory return codes - use cases are explicitly described for each function + .equ OMX_Sts_NoErr, 0 // No error the function completed successfully + .equ OMX_Sts_Err, -2 // Unknown/unspecified error + .equ OMX_Sts_InvalidBitstreamValErr, -182 // Invalid value detected during bitstream processing + .equ OMX_Sts_MemAllocErr, -9 // Not enough memory allocated for the operation + .equ OMX_StsACAAC_GainCtrErr, -159 // AAC: Unsupported gain control data detected + .equ OMX_StsACAAC_PrgNumErr, -167 // AAC: Invalid number of elements for one program + .equ OMX_StsACAAC_CoefValErr, -163 // AAC: Invalid quantized coefficient value + .equ OMX_StsACAAC_MaxSfbErr, -162 // AAC: Invalid maxSfb value in relation to numSwb + .equ OMX_StsACAAC_PlsDataErr, -160 // AAC: pulse escape sequence data error -@// Optional return codes - use cases are explicitly described for each function - .equ OMX_Sts_BadArgErr, -5 @// Bad Arguments +// Optional return codes - use cases are explicitly described for each function + .equ OMX_Sts_BadArgErr, -5 // Bad Arguments - .equ OMX_StsACAAC_TnsNumFiltErr, -157 @// AAC: Invalid number of TNS filters - .equ OMX_StsACAAC_TnsLenErr, -156 @// AAC: Invalid TNS region length - .equ OMX_StsACAAC_TnsOrderErr, -155 @// AAC: Invalid order of TNS filter - .equ OMX_StsACAAC_TnsCoefResErr, -154 @// AAC: Invalid bit-resolution for TNS filter coefficients - .equ OMX_StsACAAC_TnsCoefErr, -153 @// AAC: Invalid TNS filter coefficients - .equ OMX_StsACAAC_TnsDirectErr, -152 @// AAC: Invalid TNS filter direction - .equ OMX_StsICJP_JPEGMarkerErr, -183 @// JPEG marker encountered within an entropy-coded block; - @// Huffman decoding operation terminated early. - .equ OMX_StsICJP_JPEGMarker, -181 @// JPEG marker encountered; Huffman decoding - @// operation terminated early. - .equ OMX_StsIPPP_ContextMatchErr, -17 @// Context parameter doesn't match to the operation + .equ OMX_StsACAAC_TnsNumFiltErr, -157 // AAC: Invalid number of TNS filters + .equ OMX_StsACAAC_TnsLenErr, -156 // AAC: Invalid TNS region length + .equ OMX_StsACAAC_TnsOrderErr, -155 // AAC: Invalid order of TNS filter + .equ OMX_StsACAAC_TnsCoefResErr, -154 // AAC: Invalid bit-resolution for TNS filter coefficients + .equ OMX_StsACAAC_TnsCoefErr, -153 // AAC: Invalid TNS filter coefficients + .equ OMX_StsACAAC_TnsDirectErr, -152 // AAC: Invalid TNS filter direction + .equ OMX_StsICJP_JPEGMarkerErr, -183 // JPEG marker encountered within an entropy-coded block; + // Huffman decoding operation terminated early. + .equ OMX_StsICJP_JPEGMarker, -181 // JPEG marker encountered; Huffman decoding + // operation terminated early. + .equ OMX_StsIPPP_ContextMatchErr, -17 // Context parameter doesn't match to the operation - .equ OMX_StsSP_EvenMedianMaskSizeErr, -180 @// Even size of the Median Filter mask was replaced by the odd one + .equ OMX_StsSP_EvenMedianMaskSizeErr, -180 // Even size of the Median Filter mask was replaced by the odd one - .equ OMX_Sts_MaximumEnumeration, 0x7FFFFFFF + .equ OMX_Sts_MaximumEnumeration, 0x7FFFFFFF - .equ OMX_MIN_S8, (-128) - .equ OMX_MIN_U8, 0 - .equ OMX_MIN_S16, (-32768) - .equ OMX_MIN_U16, 0 + .equ OMX_MIN_S8, (-128) + .equ OMX_MIN_U8, 0 + .equ OMX_MIN_S16, (-32768) + .equ OMX_MIN_U16, 0 - .equ OMX_MIN_S32, (-2147483647-1) - .equ OMX_MIN_U32, 0 + .equ OMX_MIN_S32, (-2147483647-1) + .equ OMX_MIN_U32, 0 - .equ OMX_MAX_S8, (127) - .equ OMX_MAX_U8, (255) - .equ OMX_MAX_S16, (32767) - .equ OMX_MAX_U16, (0xFFFF) - .equ OMX_MAX_S32, (2147483647) - .equ OMX_MAX_U32, (0xFFFFFFFF) + .equ OMX_MAX_S8, (127) + .equ OMX_MAX_U8, (255) + .equ OMX_MAX_S16, (32767) + .equ OMX_MAX_U16, (0xFFFF) + .equ OMX_MAX_S32, (2147483647) + .equ OMX_MAX_U32, (0xFFFFFFFF) - .equ OMX_VC_UPPER, 0x1 @// Used by the PredictIntra functions - .equ OMX_VC_LEFT, 0x2 @// Used by the PredictIntra functions - .equ OMX_VC_UPPER_RIGHT, 0x40 @// Used by the PredictIntra functions + .equ OMX_VC_UPPER, 0x1 // Used by the PredictIntra functions + .equ OMX_VC_LEFT, 0x2 // Used by the PredictIntra functions + .equ OMX_VC_UPPER_RIGHT, 0x40 // Used by the PredictIntra functions - .equ NULL, 0 + .equ NULL, 0 @@ -18,6 +18,11 @@ 'include_dirs': [ '../', ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../', + ], + }, 'sources': [ 'api/omxtypes.h', 'sp/api/omxSP.h', @@ -29,6 +34,21 @@ 'BIG_FFT_TABLE', ], }], + ['target_arch=="arm" or target_arch=="arm64"', { + 'sources':[ + # Common files that are used by both arm and arm64 code. + 'api/arm/armOMX.h', + 'api/arm/omxtypes_s.h', + 'sp/api/armSP.h', + 'sp/src/arm/armSP_FFT_S32TwiddleTable.c', + 'sp/src/arm/omxSP_FFTGetBufSize_C_FC32.c', + 'sp/src/arm/omxSP_FFTGetBufSize_C_SC32.c', + 'sp/src/arm/omxSP_FFTGetBufSize_R_F32.c', + 'sp/src/arm/omxSP_FFTGetBufSize_R_S32.c', + 'sp/src/arm/omxSP_FFTInit_C_FC32.c', + 'sp/src/arm/omxSP_FFTInit_R_F32.c', + ], + }], ['target_arch=="arm"', { 'cflags!': [ '-mfpu=vfpv3-d16', @@ -44,21 +64,11 @@ 'sources': [ # Common files that are used by both the NEON and non-NEON code. 'api/armCOMM_s.h', - 'api/armOMX.h', - 'api/omxtypes_s.h', - 'sp/api/armSP.h', - 'sp/src/arm/armSP_FFT_S32TwiddleTable.c', - 'sp/src/arm/omxSP_FFTGetBufSize_C_FC32.c', 'sp/src/arm/omxSP_FFTGetBufSize_C_SC16.c', - 'sp/src/arm/omxSP_FFTGetBufSize_C_SC32.c', - 'sp/src/arm/omxSP_FFTGetBufSize_R_F32.c', 'sp/src/arm/omxSP_FFTGetBufSize_R_S16.c', 'sp/src/arm/omxSP_FFTGetBufSize_R_S16S32.c', - 'sp/src/arm/omxSP_FFTGetBufSize_R_S32.c', - 'sp/src/arm/omxSP_FFTInit_C_FC32.c', 'sp/src/arm/omxSP_FFTInit_C_SC16.c', 'sp/src/arm/omxSP_FFTInit_C_SC32.c', - 'sp/src/arm/omxSP_FFTInit_R_F32.c', 'sp/src/arm/omxSP_FFTInit_R_S16.c', 'sp/src/arm/omxSP_FFTInit_R_S16S32.c', 'sp/src/arm/omxSP_FFTInit_R_S32.c', @@ -148,6 +158,47 @@ 'sp/src/x86/x86SP_SSE_Math.h', ], }], + ['target_arch=="arm64"', { + 'sources':[ + 'api/arm/arm64COMM_s.h', + + # Complex floating-point FFT + 'sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_fs_s.S', + 'sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_ls_s.S', + 'sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_s.S', + 'sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_fs_s.S', + 'sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_ls_s.S', + 'sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_s.S', + 'sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix8_fs_s.S', + 'sp/src/arm/arm64/omxSP_FFTInv_CToC_FC32.c', + 'sp/src/arm/arm64/omxSP_FFTFwd_CToC_FC32.c', + # Real floating-point FFT + 'sp/src/arm/arm64/armSP_FFTInv_CCSToR_F32_preTwiddleRadix2_s.S', + 'sp/src/arm/arm64/omxSP_FFTFwd_RToCCS_F32.c', + 'sp/src/arm/arm64/ComplexToRealFixup.S', + 'sp/src/arm/arm64/omxSP_FFTInv_CCSToR_F32.c', + ], + }], + ['target_arch=="mipsel"', { + 'cflags': [ + '-std=c99', + ], + 'sources!': [ + 'sp/src/armSP_FFT_F32TwiddleTable.c', + ], + 'sources': [ + 'sp/api/mipsSP.h', + 'sp/src/mips/mips_FFTFwd_RToCCS_F32_complex.c', + 'sp/src/mips/mips_FFTFwd_RToCCS_F32_real.c', + 'sp/src/mips/mips_FFTInv_CCSToR_F32_complex.c', + 'sp/src/mips/mips_FFTInv_CCSToR_F32_real.c', + 'sp/src/mips/omxSP_FFT_F32TwiddleTable.c', + 'sp/src/mips/omxSP_FFTFwd_RToCCS_F32_Sfs.c', + 'sp/src/mips/omxSP_FFTGetBufSize_R_F32.c', + 'sp/src/mips/omxSP_FFTInit_R_F32.c', + 'sp/src/mips/omxSP_FFTInv_CCSToR_F32_Sfs.c', + ], + }], ], }, ], diff --git a/dl/sp/api/armSP.h b/dl/sp/api/armSP.h index 4972f09..cf17ec5 100644 --- a/dl/sp/api/armSP.h +++ b/dl/sp/api/armSP.h @@ -29,6 +29,8 @@ #ifndef _armSP_H_ #define _armSP_H_ +#include <stdint.h> + #include "dl/api/omxtypes.h" #ifdef __cplusplus @@ -88,6 +90,42 @@ typedef struct ARMsFFTSpec_FC32_Tag OMX_FC32* pBuf; } ARMsFFTSpec_FC32; +/* + * Compute log2(x), where x must be a power of 2. + */ +static inline OMX_U32 fastlog2(long x) { + OMX_U32 out; + asm("clz %0,%1\n\t" + "sub %0, %0, #63\n\t" + "neg %0, %0\n\t" + : "=r"(out) + : "r"(x) + :); + return out; +} + +/* + * Validate args. All pointers must be non-NULL; the source and + * destination pointers must be aligned on a 32-byte boundary; the + * FFT spec must have non-NULL pointers; and the FFT size must be + * within range. + */ +static inline int validateParametersFC32(const void* pSrc, + const void* pDst, + const ARMsFFTSpec_FC32* pFFTSpec) { + return pSrc && pDst && pFFTSpec && !(((uintptr_t)pSrc) & 31) && + !(((uintptr_t)pDst) & 31) && pFFTSpec->pTwiddle && pFFTSpec->pBuf && + (pFFTSpec->N >= 2) && (pFFTSpec->N <= (1 << TWIDDLE_TABLE_ORDER)); +} + +static inline int validateParametersF32(const void* pSrc, + const void* pDst, + const ARMsFFTSpec_R_FC32* pFFTSpec) { + return pSrc && pDst && pFFTSpec && !(((uintptr_t)pSrc) & 31) && + !(((uintptr_t)pDst) & 31) && pFFTSpec->pTwiddle && pFFTSpec->pBuf && + (pFFTSpec->N >= 2) && (pFFTSpec->N <= (1 << TWIDDLE_TABLE_ORDER)); +} + #ifdef __cplusplus } #endif diff --git a/dl/sp/api/mipsSP.h b/dl/sp/api/mipsSP.h new file mode 100644 index 0000000..6402e92 --- /dev/null +++ b/dl/sp/api/mipsSP.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#ifndef _MIPSSP_H_ +#define _MIPSSP_H_ + +#include "dl/api/omxtypes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Number of sub-transforms performed in the final stage of the 65536-size FFT. + * The number of sub-transforms for all other stages can be derived from this + * number. This sequence of numbers is equivalent to the Jacobsthal number + * sequence (see http://en.wikipedia.org/wiki/Jacobsthal_number). + */ +#define SUBTRANSFORM_CONST (0x2aab) +#define SQRT1_2 (0.7071067812f) /* sqrt(0.5f) */ + +extern OMX_F32 mipsSP_FFT_F32TwiddleTable[]; + +typedef struct MIPSFFTSpec_R_FC32_Tag { + OMX_U32 order; + OMX_U16* pBitRev; + OMX_U16* pBitRevInv; + const OMX_U16* pOffset; + OMX_F32* pTwiddle; + OMX_F32* pBuf; +} MIPSFFTSpec_R_FC32; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dl/sp/src/arm/arm64/ComplexToRealFixup.S b/dl/sp/src/arm/arm64/ComplexToRealFixup.S new file mode 100644 index 0000000..9b30093 --- /dev/null +++ b/dl/sp/src/arm/arm64/ComplexToRealFixup.S @@ -0,0 +1,261 @@ +// +// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// This is a modification of omxSP_FFTFwd_RToCCS_S32_Sfs_s.s +// to support float instead of SC32. +// + +// +// Description: +// Compute FFT for a real signal +// +// + + +// Include standard headers + +#include "dl/api/arm/arm64COMM_s.h" +#include "dl/api/arm/omxtypes_s.h" + + +// Import symbols required from other files +// (For example tables) + +// Set debugging level +//DEBUG_ON SETL {TRUE} + + + +// Guarding implementation by the processor name + + + + // Guarding implementation by the processor name + +// Import symbols required from other files + + +//Input Registers + +#define pSrc x0 +#define pDst x1 +#define pTwiddle x2 +#define pOut x3 +#define subFFTNum x4 + +// Output registers + +//Local Scratch Registers + +#define argTwiddle x5 +#define argDst x6 +#define subFFTSize x7 +#define N subFFTNum +#define order x14 +#define step x8 +#define step1 pTwiddle +#define twStep x9 +#define zero w10 +#define pTwiddleTmp pOut + +// Neon registers + +#define dX0 v0.2s +#define dX0s v0.s +#define dX0r v2.2s +#define dX0rs v2.s +#define dX0i v3.2s +#define dX0is v3.s +#define dX1r v4.2s +#define dX1i v5.2s +#define dT0 v6.2s +#define dT1 v7.2s +#define dT2 v8.2s +#define dT3 v9.2s +#define qT0 v10.2s +#define qT1 v12.2s +#define dW0r v14.2s +#define dW0r8b v14.8b +#define dW0i v15.2s +#define dW1r v16.2s +#define dW1r8b v16.8b +#define dW1i v17.2s +#define dY0r v14.2s +#define dY0i v15.2s +#define dY1r v16.2s +#define dY1i v17.2s +#define qT2 v18.2s +#define qT3 v20.2s + +#define half v0.2s +#define dZip v21.2s +#define dZip8b v21.8b + + // Allocate stack memory required by the function + + // Write function header + M_START ComplexToRealFixup,,d15 + + asr N, N, #1 + + clz order, subFFTNum // N = 2^order + + RSB order,order,#63 + MOV subFFTSize,subFFTNum // subFFTSize = N/2 + //MOV subFFTNum,N + mov argDst, pDst + mov argTwiddle, pTwiddle + + // F(0) = 1/2[Z(0) + Z'(0)] - j [Z(0) - Z'(0)] + // 1/2[(a+jb) + (a-jb)] - j [(a+jb) - (a-jb)] + // 1/2[2a+j0] - j [0+j2b] + // (a+b, 0) + + // F(N/2) = 1/2[Z(0) + Z'(0)] + j [Z(0) - Z'(0)] + // 1/2[(a+jb) + (a-jb)] + j [(a+jb) - (a-jb)] + // 1/2[2a+j0] + j [0+j2b] + // (a-b, 0) + + // F(0) and F(N/2) + ld2 {dX0rs,dX0is}[0],[pSrc], #8 + MOV zero,#0 + mov dX0rs[1],zero + lsl step,subFFTSize, #3 // step = N/2 * 8 bytes + mov dX0i[1],zero + // twStep = 3N/8 * 8 bytes pointing to W^1 + SUB twStep,step,subFFTSize,LSL #1 + + fadd dY0r,dX0r,dX0i // F(0) = ((Z0.r+Z0.i) , 0) + lsl step1,subFFTSize, #2 // step1 = N/2 * 4 bytes + fsub dY0i,dX0r,dX0i // F(N/2) = ((Z0.r-Z0.i) , 0) + SUBS subFFTSize,subFFTSize,#2 + + st1 {dY0r},[argDst],step + ADD pTwiddleTmp,argTwiddle,#8 // W^2 + st1 {dY0i},[argDst], #8 + ADD argTwiddle,argTwiddle,twStep // W^1 + +// dup dzero,zero + SUB argDst,argDst,step + + BLT End + BEQ lastElement + SUB step,step,#24 + SUB step1,step1,#8 // (N/4-1)*8 bytes + + // F(k) = 1/2[Z(k) + Z'(N/2-k)] -j*W^(k) [Z(k) - Z'(N/2-k)] + // Note: W^k is stored as negative values in the table + // Process 4 elements at a time. E.g: F(1),F(2) and F(N/2-2),F(N/2-1) + // since both of them require Z(1),Z(2) and Z(N/2-2),Z(N/2-1) + + fmov half, #0.5 + +evenOddButterflyLoop: + + + ld1 {dW0r},[argTwiddle],step1 + ld1 {dW1r},[argTwiddle], #8 + + ld2 {dX0r,dX0i},[pSrc],step + SUB argTwiddle,argTwiddle,step1 + ld2 {dX1r,dX1i},[pSrc], #16 + + + + SUB step1,step1,#8 // (N/4-2)*8 bytes + ld1 {dW0i},[pTwiddleTmp],step1 + ld1 {dW1i},[pTwiddleTmp], #8 + SUB pSrc,pSrc,step + + SUB pTwiddleTmp,pTwiddleTmp,step1 + rev64 dX1r,dX1r + rev64 dX1i,dX1i + SUBS subFFTSize,subFFTSize,#4 + + + + fsub dT2,dX0r,dX1r // a-c + SUB step1,step1,#8 + fadd dT0,dX0r,dX1r // a+c + fsub dT1,dX0i,dX1i // b-d + fadd dT3,dX0i,dX1i // b+d + fmul dT0,dT0,half[0] + fmul dT1,dT1,half[0] + // VZIP dW1r,dW1i + // VZIP dW0r,dW0i + zip1 dZip, dW1r, dW1i + zip2 dW1i, dW1r, dW1i + mov dW1r8b, dZip8b + zip1 dZip, dW0r, dW0i + zip2 dW0i, dW0r, dW0i + mov dW0r8b, dZip8b + + fmul qT0,dW1r,dT2 + fmul qT1,dW1r,dT3 + fmul qT2,dW0r,dT2 + fmul qT3,dW0r,dT3 + + fmla qT0,dW1i,dT3 + fmls qT1,dW1i,dT2 + + fmls qT2,dW0i,dT3 + fmla qT3,dW0i,dT2 + + + fmul dX1r,qT0,half[0] + fmul dX1i,qT1,half[0] + + fsub dY1r,dT0,dX1i // F(N/2 -1) + fadd dY1i,dT1,dX1r + fneg dY1i,dY1i + + rev64 dY1r,dY1r + rev64 dY1i,dY1i + + + fmul dX0r,qT2,half[0] + fmul dX0i,qT3,half[0] + + fsub dY0r,dT0,dX0i // F(1) + fadd dY0i,dT1,dX0r + + + st2 {dY0r,dY0i},[argDst],step + st2 {dY1r,dY1i},[argDst], #16 + SUB argDst,argDst,step + SUB step,step,#32 // (N/2-4)*8 bytes + + + BGT evenOddButterflyLoop + + // set both the ptrs to the last element + SUB pSrc,pSrc,#8 + SUB argDst,argDst,#8 + + + + // Last element can be expanded as follows + // 1/2[Z(k) + Z'(k)] + j w^k [Z(k) - Z'(k)] + // 1/2[(a+jb) + (a-jb)] + j w^k [(a+jb) - (a-jb)] + // 1/2[2a+j0] + j (c+jd) [0+j2b] + // (a-bc, -bd) + // Since (c,d) = (0,1) for the last element, result is just (a,-b) + +lastElement: + ld1 {dX0r},[pSrc] + + st1 {dX0rs}[0],[argDst], #4 + fneg dX0r,dX0r + st1 {dX0rs}[1],[argDst], #4 +End: + + // Write function tail + M_END + + .end diff --git a/dl/sp/src/arm/arm64/armSP_FFTInv_CCSToR_F32_preTwiddleRadix2_s.S b/dl/sp/src/arm/arm64/armSP_FFTInv_CCSToR_F32_preTwiddleRadix2_s.S new file mode 100644 index 0000000..da68314 --- /dev/null +++ b/dl/sp/src/arm/arm64/armSP_FFTInv_CCSToR_F32_preTwiddleRadix2_s.S @@ -0,0 +1,280 @@ +// +// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// This is a modification of +// armSP_FFTInv_CCSToR_S32_preTwiddleRadix2_unsafe_s.s to support float +// instead of SC32. +// + +// +// Description: +// Compute the "preTwiddleRadix2" stage prior to the call to the complexFFT +// It does a Z(k) = Feven(k) + jW^(-k) FOdd(k); k=0,1,2,...N/2-1 computation +// +// + + +// Include standard headers + +#include "dl/api/arm/arm64COMM_s.h" +#include "dl/api/arm/omxtypes_s.h" + + +// Import symbols required from other files +// (For example tables) + + +// Set debugging level +//DEBUG_ON SETL {TRUE} + + + +// Guarding implementation by the processor name + + + + // Guarding implementation by the processor name + + + +//Input Registers + +#define pSrc x0 +#define pTwiddle x1 +#define pOut x2 +#define subFFTNum x3 + +// Output registers + +//Local Scratch Registers + +#define argTwiddle x5 +#define argDst x6 +#define subFFTSize x7 +#define N subFFTNum + +#define pOut1 x13 + +#define size x7 +#define step x8 +#define step1 x9 +#define twStep x10 +#define pTwiddleTmp x11 +#define argTwiddle1 x12 + +// Neon registers + +#define dX0 v0.2s +#define dX0s v0.s +#define dShift v1.2s +#define dX1 v1.2s +#define dX1s v1.s +#define dY0 v2.2s +#define dY08b v2.8b +#define dY1 v3.2s +#define dX0r v0.2s +#define dX0rs v0.s +#define dX0i v1.2s +#define dX1r v2.2s +#define dX1i v3.2s +#define dW0r v4.2s +#define dW0r8b v4.8b +#define dW0i v5.2s +#define dW1r v6.2s +#define dW1r8b v6.8b +#define dW1i v7.2s +#define dT0 v8.2s +#define dT1 v9.2s +#define dT2 v10.2s +#define dT3 v11.2s +#define qT0 v12.2s +#define qT1 v14.2s +#define qT2 v16.2s +#define qT3 v18.2s +#define dY0r v4.2s +#define dY0i v5.2s +#define dY1r v6.2s +#define dY1i v7.2s + +#define dY2 v4.2s +#define dY3 v5.2s +#define dW0 v6.2s +#define dW1 v7.2s +#define dW0Tmp v10.2s +#define dW1Neg v11.2s + +#define dZip v19.2s +#define dZip8b v19.8b +#define half v13.2s + + .MACRO FFTSTAGE scaled, inverse, name + + fmov half, 0.5 + + asr size, subFFTNum, #1 // preserve the contents of N = subFFTNum + lsl step, subFFTNum, #2 // step = N/2 * 8 bytes + + + // Z(k) = 1/2 {[F(k) + F'(N/2-k)] +j*W^(-k) [F(k) - F'(N/2-k)]} + // Note: W^(k) is stored as negated value and also need to + // conjugate the values from the table + + // Z(0) : no need of twiddle multiply + // Z(0) = 1/2 { [F(0) + F'(N/2)] +j [F(0) - F'(N/2)] } + + ld1 {dX0},[pSrc],step + ADD pOut1,pOut,step // pOut1 = pOut+ N/2*8 bytes + + ld1 {dX1},[pSrc], #8 + // twStep = 3N/8 * 8 bytes pointing to W^1 + SUB twStep,step,size,LSL #1 + + lsl step1,size, #2 // step1 = N/4 * 8 = N/2*4 bytes + SUB step1,step1,#8 // (N/4-1)*8 bytes + + fadd dY0,dX0,dX1 // [b+d | a+c] + fsub dY1,dX0,dX1 // [b-d | a-c] + fmul dY0, dY0, half[0] + fmul dY1, dY1, half[0] + + // dY0= [a-c | a+c] ;dY1= [b-d | b+d] + // VZIP dY0,dY1 + zip1 dZip,dY0,dY1 + zip2 dY1,dY0,dY1 + mov dY08b, dZip8b + + fsub dX0,dY0,dY1 + SUBS size,size,#2 + fadd dX1,dY0,dY1 + + SUB pSrc,pSrc,step + + st1 {dX0s}[0],[pOut1], #4 + ADD pTwiddleTmp,pTwiddle,#8 // W^2 + st1 {dX1s}[1],[pOut1], #4 + ADD argTwiddle1,pTwiddle,twStep // W^1 + + + BLT decrementScale\name + BEQ lastElement\name + + + // Z(k) = 1/2[F(k) + F'(N/2-k)] +j*W^(-k) [F(k) - F'(N/2-k)] + // Note: W^k is stored as negative values in the table and also + // need to conjugate the values from the table. + // + // Process 4 elements at a time. E.g: Z(1),Z(2) and Z(N/2-2),Z(N/2-1) + // since both of them require F(1),F(2) and F(N/2-2),F(N/2-1) + + + SUB step,step,#24 +evenOddButterflyLoop\name : + + + ld1 {dW0r},[argTwiddle1],step1 + ld1 {dW1r},[argTwiddle1], #8 + + ld2 {dX0r,dX0i},[pSrc],step + SUB argTwiddle1,argTwiddle1,step1 + ld2 {dX1r,dX1i},[pSrc], #16 + + SUB step1,step1,#8 // (N/4-2)*8 bytes + ld1 {dW0i},[pTwiddleTmp],step1 + ld1 {dW1i},[pTwiddleTmp], #8 + SUB pSrc,pSrc,step + + SUB pTwiddleTmp,pTwiddleTmp,step1 + rev64 dX1r,dX1r + rev64 dX1i,dX1i + SUBS size,size,#4 + + + fsub dT2,dX0r,dX1r // a-c + fadd dT3,dX0i,dX1i // b+d + fadd dT0,dX0r,dX1r // a+c + fsub dT1,dX0i,dX1i // b-d + SUB step1,step1,#8 + + fmul dT2, dT2, half[0] + fmul dT3, dT3, half[0] + + fmul dT0, dT0, half[0] + fmul dT1, dT1, half[0] + + // VZIP dW1r,dW1i + // VZIP dW0r,dW0i + zip1 dZip, dW1r,dW1i + zip2 dW1i,dW1r,dW1i + mov dW1r8b, dZip8b + zip1 dZip,dW0r,dW0i + zip2 dW0i,dW0r,dW0i + mov dW0r8b, dZip8b + + fmul dX1r,dW1r,dT2 + fmul dX1i,dW1r,dT3 + fmul dX0r,dW0r,dT2 + fmul dX0i,dW0r,dT3 + + fmls dX1r,dW1i,dT3 + fmla dX1i,dW1i,dT2 + + fmla dX0r,dW0i,dT3 + fmls dX0i,dW0i,dT2 + + + fadd dY1r,dT0,dX1i // F(N/2 -1) + fsub dY1i,dX1r,dT1 + + rev64 dY1r,dY1r + rev64 dY1i,dY1i + + + fadd dY0r,dT0,dX0i // F(1) + fsub dY0i,dT1,dX0r + + + st2 {dY0r,dY0i},[pOut1],step + st2 {dY1r,dY1i},[pOut1], #16 + SUB pOut1,pOut1,step + SUB step,step,#32 // (N/2-4)*8 bytes + + + BGT evenOddButterflyLoop\name + + + // set both the ptrs to the last element + SUB pSrc,pSrc,#8 + SUB pOut1,pOut1,#8 + + // Last element can be expanded as follows + // 1/2[Z(k) + Z'(k)] - j w^-k [Z(k) - Z'(k)] (since W^k is stored as + // -ve) + // 1/2[(a+jb) + (a-jb)] - j w^-k [(a+jb) - (a-jb)] + // 1/2[2a+j0] - j (c-jd) [0+j2b] + // (a+bc, -bd) + // Since (c,d) = (0,1) for the last element, result is just (a,-b) + +lastElement\name : + ld1 {dX0r},[pSrc] + + st1 {dX0rs}[0],[pOut1], #4 + fneg dX0r,dX0r + st1 {dX0rs}[1],[pOut1] + + + +decrementScale\name : + + .endm + + M_START armSP_FFTInv_CCSToR_F32_preTwiddleRadix2,,d15 + FFTSTAGE "FALSE","TRUE",Inv + M_END + + .end diff --git a/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_fs_s.S b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_fs_s.S new file mode 100644 index 0000000..b22912d --- /dev/null +++ b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_fs_s.S @@ -0,0 +1,136 @@ +// +// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// This is a modification of armSP_FFT_CToC_SC32_Radix2_fs_unsafe_s.S +// to support float instead of SC32. +// + +// +// Description: +// Compute the first stage of a Radix 2 DIT in-order out-of-place FFT +// stage for a N point complex signal. +// +// + + +// Include standard headers + +#include "dl/api/arm/arm64COMM_s.h" +#include "dl/api/arm/omxtypes_s.h" + + +// Import symbols required from other files +// (For example tables) + + + + +// Set debugging level +//DEBUG_ON SETL {TRUE} + + + +// Guarding implementation by the processor name + + + +// Guarding implementation by the processor name + + +//Input Registers + +#define pSrc x0 +#define pDst x1 +#define pTwiddle x2 +#define pSubFFTNum x3 +#define pSubFFTSize x4 + + +//Output Registers + + +//Local Scratch Registers + +#define subFFTNum x5 +#define subFFTSize x6 +#define pointStep x7 +#define outPointStep x7 +#define grpSize x8 +#define setCount x8 +#define step x9 +#define dstStep x9 + +// Neon Registers +#define dX0 v0.2s +#define dX1 v1.2s +#define dY0 v2.2s +#define dY1 v3.2s + + .MACRO FFTSTAGE scaled, inverse, name + + // Define stack arguments + + // Move args values into our work registers + ldr subFFTNum, [pSubFFTNum] + ldr subFFTSize, [pSubFFTSize] + + // update subFFTSize and subFFTNum into RN6 and RN7 for the next stage + + + MOV subFFTSize,#2 + LSR grpSize,subFFTNum,#1 + MOV subFFTNum,grpSize + + + // pT0+1 increments pT0 by 8 bytes + // pT0+pointStep = increment of 8*pointStep bytes = 4*grpSize bytes + // Note: outPointStep = pointStep for firststage + // Note: setCount = grpSize/2 (reuse the updated grpSize for setCount) + + lsl pointStep, grpSize, #3 + rsb step, pointStep, #8 + + // Loop on the sets for grp zero + +grpZeroSetLoop\name : + + LD1 {dX0},[pSrc],pointStep + LD1 {dX1},[pSrc],step // step = -pointStep + 8 + + SUBS setCount,setCount,#1 + + fadd dY0,dX0,dX1 + fsub dY1,dX0,dX1 + + ST1 {dY0},[pDst],outPointStep + // dstStep = step = -pointStep + 8 + ST1 {dY1},[pDst],dstStep + + BGT grpZeroSetLoop\name + + + // Save subFFTNum and subFFTSize for next stage + str subFFTNum, [pSubFFTNum] + str subFFTSize, [pSubFFTSize] + + .endm + + + + M_START armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace + FFTSTAGE "FALSE","FALSE",fwd + M_END + + + + M_START armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace + FFTSTAGE "FALSE","TRUE",inv + M_END + + .end diff --git a/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_ls_s.S b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_ls_s.S new file mode 100644 index 0000000..e7de11e --- /dev/null +++ b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_ls_s.S @@ -0,0 +1,149 @@ +// +// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// This is a modification of armSP_FFT_CToC_SC32_Radix2_ls_unsafe_s.S +// to support float instead of SC32. +// + +// +// Description: +// Compute the last stage of a Radix 2 DIT in-order out-of-place FFT +// stage for a N point complex signal. +// +// + + +// Include standard headers + +#include "dl/api/arm/arm64COMM_s.h" +#include "dl/api/arm/omxtypes_s.h" + + +// Import symbols required from other files +// (For example tables) + + + + +// Set debugging level +//DEBUG_ON SETL {TRUE} + + +// Guarding implementation by the processor name + + +//Input Registers + +#define pSrc x0 +#define pDst x1 +#define pTwiddle x2 +#define pSubFFTNum x3 +#define pSubFFTSize x4 + + +//Output Registers + + +//Local Scratch Registers + + +#define subFFTNum x5 +#define subFFTSize x6 +#define outPointStep x8 +#define grpCount x9 +#define dstStep x10 + +// Neon Registers + +#define dWr v0.2s +#define dWi v1.2s +#define dXr0 v2.2s +#define dXi0 v3.2s +#define dXr1 v4.2s +#define dXi1 v5.2s +#define dYr0 v6.2s +#define dYi0 v7.2s +#define dYr1 v8.2s +#define dYi1 v9.2s +#define qT0 v10.2s +#define qT1 v12.2s + + .MACRO FFTSTAGE scaled, inverse, name + + // Move parameters into our work registers + ldr subFFTSize, [pSubFFTSize] + + lsl outPointStep, subFFTSize, #3 + + // Update grpCount and grpSize rightaway + + MOV subFFTNum,#1 //after the last stage + LSL grpCount,subFFTSize,#1 + + // update subFFTSize for the next stage + MOV subFFTSize,grpCount + + rsb dstStep,outPointStep,#16 + + // Loop on 2 grps at a time for the last stage + +radix2lsGrpLoop\name : + // dWr = [pTwiddle[0].Re, pTwiddle[1].Re] + // dWi = [pTwiddle[0].Im, pTwiddle[1].Im] + ld2 {dWr,dWi},[pTwiddle], #16 + + // dXr0 = [pSrc[0].Re, pSrc[2].Re] + // dXi0 = [pSrc[0].Im, pSrc[2].Im] + // dXr1 = [pSrc[1].Re, pSrc[3].Re] + // dXi1 = [pSrc[1].Im, pSrc[3].Im] + ld4 {dXr0,dXi0,dXr1,dXi1}, [pSrc], #32 + + SUBS grpCount,grpCount,#4 // grpCount is multiplied by 2 + + .ifeqs "\inverse", "TRUE" + fmul qT0,dWr,dXr1 + fmla qT0,dWi,dXi1 // real part + fmul qT1,dWr,dXi1 + fmls qT1,dWi,dXr1 // imag part + + .else + + fmul qT0,dWr,dXr1 + fmls qT0,dWi,dXi1 // real part + fmul qT1,dWr,dXi1 + fmla qT1,dWi,dXr1 // imag part + + .endif + + fsub dYr0,dXr0,qT0 + fsub dYi0,dXi0,qT1 + fadd dYr1,dXr0,qT0 + fadd dYi1,dXi0,qT1 + + st2 {dYr0,dYi0},[pDst],outPointStep + st2 {dYr1,dYi1},[pDst],dstStep // dstStep = step = -outPointStep + 16 + + BGT radix2lsGrpLoop\name + + + .endm + + + + M_START armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace,,d12 + FFTSTAGE "FALSE","FALSE",fwd + M_END + + + + M_START armSP_FFTInv_CToC_FC32_Radix2_ls_OutOfPlace,,d12 + FFTSTAGE "FALSE","TRUE",inv + M_END + + .end diff --git a/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_s.S b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_s.S new file mode 100644 index 0000000..530a815 --- /dev/null +++ b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix2_s.S @@ -0,0 +1,185 @@ +// +// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// This is a modification of armSP_FFT_CToC_SC32_Radix2_unsafe_s.s +// to support float instead of SC32. +// + +// Description: +// Compute a Radix 2 DIT in-order out-of-place FFT stage for an N point +// complex signal. This handles the general stage, not the first or last +// stage. +// +// + + +// Include standard headers + +#include "dl/api/arm/arm64COMM_s.h" +#include "dl/api/arm/omxtypes_s.h" + + +// Import symbols required from other files +// (For example tables) + + + +// Set debugging level +//DEBUG_ON SETL {TRUE} + + + +// Guarding implementation by the processor name + + + + +// Guarding implementation by the processor name + +//Input Registers + +#define pSrc x0 +#define pDst x1 +#define pTwiddle x2 +#define pSubFFTNum x3 +#define pSubFFTSize x4 + + +//Output Registers + + +//Local Scratch Registers + +#define subFFTNum x5 +#define subFFTSize x6 +#define outPointStep x8 +#define pointStep x9 +#define pointStep32 w9 +#define grpCount x10 +#define grpCount32 w10 +#define setCount x13 +#define step x15 +#define dstStep x11 + +// Neon Registers + +#define dW v0.2s +#define dX0 v2.2s +#define dX1 v3.2s +#define dX2 v4.2s +#define dX3 v5.2s +#define dY0 v6.2s +#define dY1 v7.2s +#define dY2 v8.2s +#define dY3 v9.2s +#define qT0 v10.2s +#define qT1 v11.2s + + .MACRO FFTSTAGE scaled, inverse, name + + // Define stack arguments + + // Move args values into our work registers + ldr subFFTNum, [pSubFFTNum] + ldr subFFTSize, [pSubFFTSize] + + // Update grpCount and grpSize rightaway inorder to reuse pGrpCount + // and pGrpSize regs + + LSR subFFTNum,subFFTNum,#1 //grpSize + LSL grpCount,subFFTSize,#1 + + + // pT0+1 increments pT0 by 8 bytes + // pT0+pointStep = increment of 8*pointStep bytes = 4*grpSize bytes + lsl pointStep, subFFTNum, #2 + + // update subFFTSize for the next stage + MOV subFFTSize,grpCount + + // pOut0+1 increments pOut0 by 8 bytes + // pOut0+outPointStep == increment of 8*outPointStep bytes = + // 4*size bytes + smull outPointStep, grpCount32, pointStep32 + + LSL pointStep,pointStep,#1 + + + rsb step,pointStep,#16 + rsb dstStep,outPointStep,#16 + + // Loop on the groups + +radix2GrpLoop\name : + lsr setCount, pointStep, #3 + LD1 {dW},[pTwiddle],pointStep //[wi | wr] + + + // Loop on the sets + + +radix2SetLoop\name : + + + // point0: dX0-real part dX1-img part + LD2 {dX0,dX1},[pSrc],pointStep + // point1: dX2-real part dX3-img part + LD2 {dX2,dX3},[pSrc],step + + SUBS setCount,setCount,#2 + + .ifeqs "\inverse", "TRUE" + fmul qT0,dX2,dW[0] + fmla qT0,dX3,dW[1] // real part + fmul qT1,dX3,dW[0] + fmls qT1,dX2,dW[1] // imag part + + .else + + fmul qT0,dX2,dW[0] + fmls qT0,dX3,dW[1] // real part + fmul qT1,dX3,dW[0] + fmla qT1,dX2,dW[1] // imag part + + .endif + + fsub dY0,dX0,qT0 + fsub dY1,dX1,qT1 + fadd dY2,dX0,qT0 + fadd dY3,dX1,qT1 + + st2 {dY0,dY1},[pDst],outPointStep + // dstStep = -outPointStep + 16 + st2 {dY2,dY3},[pDst],dstStep + + BGT radix2SetLoop\name + + SUBS grpCount,grpCount,#2 + ADD pSrc,pSrc,pointStep + BGT radix2GrpLoop\name + + + str subFFTNum, [pSubFFTNum] + str subFFTSize, [pSubFFTSize] + .endm + + + + M_START armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace,,d11 + FFTSTAGE "FALSE","FALSE",FWD + M_END + + + + M_START armSP_FFTInv_CToC_FC32_Radix2_OutOfPlace,,d11 + FFTSTAGE "FALSE","TRUE",INV + M_END + + + .end diff --git a/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_fs_s.S b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_fs_s.S new file mode 100644 index 0000000..624ef3e --- /dev/null +++ b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_fs_s.S @@ -0,0 +1,266 @@ +// +// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// +// This is a modification of armSP_FFT_CToC_SC32_Radix4_fs_unsafe_s.s +// to support float instead of SC32. +// + +// +// Description: +// Compute a first stage Radix 4 FFT stage for a N point complex signal +// +// + + +// Include standard headers + +#include "dl/api/arm/arm64COMM_s.h" +#include "dl/api/arm/omxtypes_s.h" + +// Import symbols required from other files +// (For example tables) + + + + +// Set debugging level +//DEBUG_ON SETL {TRUE} + + + +// Guarding implementation by the processor name + + + +// Guarding implementation by the processor name + +//Input Registers + +#define pSrc x0 +#define pDst x1 +#define pTwiddle x2 +#define pSubFFTNum x3 +#define pSubFFTSize x4 + + +//Output Registers + + +//Local Scratch Registers + +#define subFFTNum x5 +#define subFFTSize x6 +#define grpSize x7 +// Reuse grpSize as setCount +#define setCount x7 +#define pointStep x8 +#define outPointStep x8 +#define setStep x9 +#define step1 x10 +#define step3 x11 + +// Neon Registers + +#define dXr0 v0.2s +#define dXi0 v1.2s +#define dXr1 v2.2s +#define dXi1 v3.2s +#define dXr2 v4.2s +#define dXi2 v5.2s +#define dXr3 v6.2s +#define dXi3 v7.2s +#define dYr0 v8.2s +#define dYi0 v9.2s +#define dYr1 v10.2s +#define dYi1 v11.2s +#define dYr2 v12.2s +#define dYi2 v13.2s +#define dYr3 v14.2s +#define dYi3 v15.2s +#define dZr0 v16.2s +#define dZi0 v17.2s +#define dZr1 v18.2s +#define dZi1 v19.2s +#define dZr2 v20.2s +#define dZi2 v21.2s +#define dZr3 v22.2s +#define dZi3 v23.2s + + + .MACRO FFTSTAGE scaled, inverse, name + + // Define stack arguments + + // Move args values into our work registers + ldr subFFTNum, [pSubFFTNum] + ldr subFFTSize, [pSubFFTSize] + + // pT0+1 increments pT0 by 8 bytes + // pT0+pointStep = increment of 8*pointStep bytes = 2*grpSize bytes + // Note: outPointStep = pointStep for firststage + + lsl pointStep, subFFTNum, #1 + + // Update pSubFFTSize and pSubFFTNum regs + ld2 {dXr0,dXi0}, [pSrc], pointStep // data[0] + + // subFFTSize = 1 for the first stage + MOV subFFTSize,#4 + + // Note: setCount = subFFTNum/4 (reuse the grpSize reg for setCount) + LSR grpSize,subFFTNum,#2 + ld2 {dXr1,dXi1}, [pSrc], pointStep // data[1] + MOV subFFTNum,grpSize + + + // Calculate the step of input data for the next set + //MOV setStep,pointStep,LSL #1 + lsl setStep, grpSize, #4 + ld2 {dXr2,dXi2}, [pSrc], pointStep // data[2] + + // setStep = 3*pointStep + ADD setStep,setStep,pointStep + // setStep = - 3*pointStep+16 + + rsb setStep,setStep,#16 + // data[3] & update pSrc for the next set + ld2 {dXr3,dXi3}, [pSrc], setStep + + // step1 = 2*pointStep + lsl step1, pointStep, #1 + + // fadd qY0, qX0, qX2 + fadd dYr0, dXr0, dXr2 + fadd dYi0, dXi0, dXi2 + // step3 = -pointStep + neg step3, pointStep + + // grp = 0 a special case since all the twiddle factors are 1 + // Loop on the sets : 2 sets at a time + +radix4fsGrpZeroSetLoop\name : + + + + // Decrement setcount + SUBS setCount,setCount,#2 + + + // finish first stage of 4 point FFT + + + // fsub qy2,qx0,qx2 + fsub dYr2, dXr0, dXr2 + fsub dYi2, dXi0, dXi2 + + ld2 {dXr0,dXi0}, [pSrc], step1 // data[0] + // fadd qy1,qx1,qx3 + fadd dYr1, dXr1, dXr3 + fadd dYi1, dXi1, dXi3 + ld2 {dXr2,dXi2}, [pSrc], step3 // data[2] + // fsub qy3,qx1,qx3 + fsub dYr3, dXr1, dXr3 + fsub dYi3, dXi1, dXi3 + + + // finish second stage of 4 point FFT + + .ifeqs "\inverse", "TRUE" + + ld2 {dXr1,dXi1}, [pSrc], step1 // data[1] + // fadd qz0,qy0,qy1 + fadd dZr0, dYr0, dYr1 + fadd dZi0, dYi0, dYi1 + + // data[3] & update pSrc for the next set, but not if it's the + // last iteration so that we don't read past the end of the + // input array. + BEQ radix4SkipLastUpdateInv\name + ld2 {dXr3,dXi3}, [pSrc], setStep + +radix4SkipLastUpdateInv\name: + FSUB dZr3,dYr2,dYi3 + + st2 {dZr0,dZi0},[pDst],outPointStep + FADD dZi3,dYi2,dYr3 + + // fsub qZ1,qY0,qY1 + FSUB dZr1, dYr0, dYr1 + FSUB dZi1, dYi0, dYi1 + st2 {dZr3,dZi3},[pDst],outPointStep + + FADD dZr2,dYr2,dYi3 + st2 {dZr1,dZi1},[pDst],outPointStep + FSUB dZi2,dYi2,dYr3 + + // fadd qY0, qX0, qX2 + FADD dYr0, dXr0, dXr2 // u0 for next iteration + FADD dYi0, dXi0, dXi2 + st2 {dZr2,dZi2},[pDst],setStep + + + .else + + ld2 {dXr1,dXi1}, [pSrc], step1 // data[1] + // fadd qZ0,qY0,qY1 + fadd dZr0, dYr0, dYr1 + fadd dZi0, dYi0, dYi1 + + // data[3] & update pSrc for the next set, but not if it's the + // last iteration so that we don't read past the end of the + // input array. + BEQ radix4SkipLastUpdateFwd\name + ld2 {dXr3,dXi3}, [pSrc], setStep + +radix4SkipLastUpdateFwd\name: + FADD dZr2,dYr2,dYi3 + + st2 {dZr0,dZi0},[pDst],outPointStep + FSUB dZi2,dYi2,dYr3 + + // fsub qz1,qy0,qy1 + fsub dZr1, dYr0, dYr1 + fsub dZi1, dYi0, dYi1 + st2 {dZr2,dZi2},[pDst],outPointStep + + FSUB dZr3,dYr2,dYi3 + st2 {dZr1,dZi1},[pDst],outPointStep + FADD dZi3,dYi2,dYr3 + + // fadd qy0,qx0,qx2 + fadd dYr0, dXr0, dXr2 // u0 for next iteration + fadd dYi0, dXi0, dXi2 + + st2 {dZr3,dZi3},[pDst],setStep + + .endif + + BGT radix4fsGrpZeroSetLoop\name + + // Save subFFTNum and subFFTSize for next stage + str subFFTNum, [pSubFFTNum] + str subFFTSize, [pSubFFTSize] + + .endm + + + + M_START armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace,,d15 + FFTSTAGE "FALSE","FALSE",fwd + M_END + + + + M_START armSP_FFTInv_CToC_FC32_Radix4_fs_OutOfPlace,,d15 + FFTSTAGE "FALSE","TRUE",inv + M_END + + + .end diff --git a/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_ls_s.S b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_ls_s.S new file mode 100644 index 0000000..2fc2e60 --- /dev/null +++ b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_ls_s.S @@ -0,0 +1,371 @@ +// +// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// This is a modification of armSP_FFT_CToC_SC32_Radix4_ls_unsafe_s.s +// to support float instead of SC32. +// + +// +// Description: +// Compute a Radix 4 FFT stage for a N point complex signal +// +// + + +// Include standard headers + +#include "dl/api/arm/arm64COMM_s.h" +#include "dl/api/arm/omxtypes_s.h" + +// Import symbols required from other files +// (For example tables) + + + + +// Set debugging level +//DEBUG_ON SETL {TRUE} + + +// Guarding implementation by the processor name + + +// Import symbols required from other files +// (For example tables) + //IMPORT armAAC_constTable + +//Input Registers + +#define pSrc x0 +#define pDst x1 +#define pTwiddle x2 +#define pSubFFTNum x3 +#define pSubFFTSize x4 + + + +//Output Registers + + +//Local Scratch Registers + +#define subFFTNum x5 +#define subFFTSize x6 +#define outPointStep x8 +#define grpCount x9 +#define dstStep x10 +#define grpTwStep x13 +#define stepTwiddle x14 +#define twStep x15 +#define step16 x11 +#define step24 x12 + + +// Neon Registers + +#define dButterfly1Real02 v0.2s +#define dButterfly1Real028b v0.8b +#define dButterfly1Imag02 v1.2s +#define dButterfly1Imag028b v1.8b +#define dButterfly1Real13 v2.2s +#define dButterfly1Real138b v2.8b +#define dButterfly1Imag13 v3.2s +#define dButterfly1Imag138b v3.8b +#define dButterfly2Real02 v4.2s +#define dButterfly2Imag02 v5.2s +#define dButterfly2Real13 v6.2s +#define dButterfly2Imag13 v7.2s +#define dXr0 v0.2s +#define dXi0 v1.2s +#define dXr08b v0.8b +#define dXi08b v1.8b +#define dXr1 v2.2s +#define dXi1 v3.2s +#define dXr2 v4.2s +#define dXi2 v5.2s +#define dXr3 v6.2s +#define dXi3 v7.2s + +#define dYr0 v16.2s +#define dYi0 v17.2s +#define dYr1 v18.2s +#define dYi1 v19.2s +#define dYr2 v20.2s +#define dYi2 v21.2s +#define dYr3 v22.2s +#define dYi3 v23.2s + +#define dW1r v8.2s +#define dW1i v9.2s +#define dW2r v10.2s +#define dW2r8b v10.8b +#define dW2i v11.2s +#define dW3r v12.2s +#define dW3r8b v12.8b +#define dW3i v13.2s + +#define dZr0 v14.2s +#define dZi0 v15.2s +#define dZr08b v14.8b +#define dZi08b v15.8b +#define dZr1 v26.2s +#define dZi1 v27.2s +#define dZr2 v28.2s +#define dZi2 v29.2s +#define dZr3 v30.2s +#define dZi3 v31.2s + +#define dZip v24.2s +#define dZip8b v24.8b + + .MACRO FFTSTAGE scaled, inverse , name + + // Define stack arguments + + // Move args values into our work registers + ldr subFFTNum, [pSubFFTNum] + ldr subFFTSize, [pSubFFTSize] + + // pOut0+1 increments pOut0 by 8 bytes + // pOut0+outPointStep == increment of 8*outPointStep bytes + lsl outPointStep,subFFTSize, #3 + + // Update grpCount and grpSize rightaway + + ld2 {dW1r,dW1i},[pTwiddle] // [wi|wr] + MOV step16,#16 + LSL grpCount,subFFTSize,#2 + + ld1 {dW2r},[pTwiddle] // [wi|wr] + MOV subFFTNum,#1 //after the last stage + + ld1 {dW3r},[pTwiddle],step16 // [wi|wr] + MOV stepTwiddle,#0 + + ld1 {dW2i},[pTwiddle],#8 // [wi|wr] + SUB grpTwStep,stepTwiddle,#8 // grpTwStep = -8 to start with + + // update subFFTSize for the next stage + MOV subFFTSize,grpCount + ld1 {dW3i},[pTwiddle],grpTwStep // [wi|wr] + lsl dstStep,outPointStep, #1 + + // AC.r AC.i BD.r BD.i + ld4 {dButterfly1Real02,dButterfly1Imag02,dButterfly1Real13,dButterfly1Imag13},[pSrc], #32 + ADD dstStep,dstStep,outPointStep // dstStep = 3*outPointStep + + rsb dstStep,dstStep,#16 // dstStep = - 3*outPointStep+16 + MOV step24,#24 + + // AC.r AC.i BD.r BD.i + ld4 {dButterfly2Real02,dButterfly2Imag02,dButterfly2Real13,dButterfly2Imag13},[pSrc], #32 + + + // Process two groups at a time + +radix4lsGrpLoop\name : + + // VZIP dW2r,dW2i + zip1 dZip, dW2r, dW2i + zip2 dW2i, dW2r, dW2i + mov dW2r8b, dZip8b + + ADD stepTwiddle,stepTwiddle,#16 + + // VZIP dW3r,dW3i + zip1 dZip, dW3r,dW3i + zip2 dW3i, dW3r, dW3i + mov dW3r8b, dZip8b + ADD grpTwStep,stepTwiddle,#4 + + // VUZP dButterfly1Real13, dButterfly2Real13 // B.r D.r + uzp1 dZip, dButterfly1Real13, dButterfly2Real13 // B.r D.r + uzp2 dButterfly2Real13, dButterfly1Real13, dButterfly2Real13 // B.r D.r + mov dButterfly1Real138b, dZip8b + + SUB twStep,stepTwiddle,#16 // -16+stepTwiddle + + // VUZP dButterfly1Imag13, dButterfly2Imag13 // B.i D.i + uzp1 dZip, dButterfly1Imag13, dButterfly2Imag13 // B.i D.i + uzp2 dButterfly2Imag13, dButterfly1Imag13, dButterfly2Imag13 // B.i D.i + mov dButterfly1Imag138b, dZip8b + lsl grpTwStep,grpTwStep,#1 + + // VUZP dButterfly1Real02, dButterfly2Real02 // A.r C.r + uzp1 dZip, dButterfly1Real02, dButterfly2Real02 // A.r C.r + uzp2 dButterfly2Real02, dButterfly1Real02, dButterfly2Real02 // A.r C.r + mov dButterfly1Real028b, dZip8b + rsb grpTwStep,grpTwStep,#0 // -8-2*stepTwiddle + + // VUZP dButterfly1Imag02, dButterfly2Imag02 // A.i C.i + uzp1 dZip, dButterfly1Imag02, dButterfly2Imag02 // A.i C.i + uzp2 dButterfly2Imag02, dButterfly1Imag02, dButterfly2Imag02 // A.i C.i + mov dButterfly1Imag028b, dZip8b + + + // grpCount is multiplied by 4 + SUBS grpCount,grpCount,#8 + + .ifeqs "\inverse", "TRUE" + fmul dZr1,dW1r,dXr1 + fmla dZr1,dW1i,dXi1 // real part + fmul dZi1,dW1r,dXi1 + fmls dZi1,dW1i,dXr1 // imag part + + .else + + fmul dZr1,dW1r,dXr1 + fmls dZr1,dW1i,dXi1 // real part + fmul dZi1,dW1r,dXi1 + fmla dZi1,dW1i,dXr1 // imag part + + .endif + + ld2 {dW1r,dW1i},[pTwiddle],stepTwiddle // [wi|wr] + + .ifeqs "\inverse", "TRUE" + fmul dZr2,dW2r,dXr2 + fmla dZr2,dW2i,dXi2 // real part + fmul dZi2,dW2r,dXi2 + ld1 {dW2r},[pTwiddle],step16 // [wi|wr] + fmls dZi2,dW2i,dXr2 // imag part + + .else + + fmul dZr2,dW2r,dXr2 + fmls dZr2,dW2i,dXi2 // real part + fmul dZi2,dW2r,dXi2 + ld1 {dW2r},[pTwiddle],step16 // [wi|wr] + fmla dZi2,dW2i,dXr2 // imag part + + .endif + + + ld1 {dW2i},[pTwiddle],twStep // [wi|wr] + + // move qX0 so as to load for the next iteration + // MOV qZ0,qX0 + mov dZr08b, dXr08b + mov dZi08b, dXi08b + + .ifeqs "\inverse", "TRUE" + fmul dZr3,dW3r,dXr3 + fmla dZr3,dW3i,dXi3 // real part + fmul dZi3,dW3r,dXi3 + ld1 {dW3r},[pTwiddle],step24 + fmls dZi3,dW3i,dXr3 // imag part + + .else + + fmul dZr3,dW3r,dXr3 + fmls dZr3,dW3i,dXi3 // real part + fmul dZi3,dW3r,dXi3 + ld1 {dW3r},[pTwiddle],step24 + fmla dZi3,dW3i,dXr3 // imag part + + .endif + + ld1 {dW3i},[pTwiddle],grpTwStep // [wi|wr] + + // Don't do the load on the last iteration so we don't read past the end + // of pSrc. + bne skipIncrement\name + add pSrc, pSrc, #64 +skipIncrement\name: + beq radix4lsSkipRead\name + // AC.r AC.i BD.r BD.i + ld4 {dButterfly1Real02,dButterfly1Imag02,dButterfly1Real13,dButterfly1Imag13},[pSrc], #32 + + // AC.r AC.i BD.r BD.i + ld4 {dButterfly2Real02,dButterfly2Imag02,dButterfly2Real13,dButterfly2Imag13},[pSrc], #32 +radix4lsSkipRead\name: + + // finish first stage of 4 point FFT + + // fadd qY0,qZ0,qZ2 + fadd dYr0,dZr0,dZr2 + fadd dYi0,dZi0,dZi2 + // fsub qY2,qZ0,qZ2 + fsub dYr2,dZr0,dZr2 + fsub dYi2,dZi0,dZi2 + // fadd qY1,qZ1,qZ3 + fadd dYr1,dZr1,dZr3 + fadd dYi1,dZi1,dZi3 + // fsub qY3,qZ1,qZ3 + fsub dYr3,dZr1,dZr3 + fsub dYi3,dZi1,dZi3 + + + // finish second stage of 4 point FFT + + .ifeqs "\inverse", "TRUE" + + // fsub qZ0,qY2,qY1 + fsub dZr0,dYr2,dYr1 + fsub dZi0,dYi2,dYi1 + fadd dZr3,dYr0,dYi3 + st2 {dZr0,dZi0},[pDst],outPointStep + fsub dZi3,dYi0,dYr3 + + // fadd qZ2,qY2,qY1 + fadd dZr2,dYr2,dYr1 + fadd dZi2,dYi2,dYi1 + + st2 {dZr3,dZi3},[pDst],outPointStep + + fsub dZr1,dYr0,dYi3 + st2 {dZr2,dZi2},[pDst],outPointStep + fadd dZi1,dYi0,dYr3 + + // dstStep = -outPointStep + 16 + st2 {dZr1,dZi1},[pDst],dstStep + + + .else + + // fsub qZ0,qY2,qY1 + fsub dZr0,dYr2,dYr1 + fsub dZi0,dYi2,dYi1 + + fsub dZr1,dYr0,dYi3 + st2 {dZr0,dZi0},[pDst],outPointStep + fadd dZi1,dYi0,dYr3 + + // fadd qZ2,qY2,qY1 + fadd dZr2,dYr2,dYr1 + fadd dZi2,dYi2,dYi1 + + st2 {dZr1,dZi1},[pDst],outPointStep + + fadd dZr3,dYr0,dYi3 + st2 {dZr2,dZi2},[pDst],outPointStep + fsub dZi3,dYi0,dYr3 + + // dstStep = -outPointStep + 16 + st2 {dZr3,dZi3},[pDst],dstStep + + + .endif + + BGT radix4lsGrpLoop\name + + .endm + + + M_START armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace,,d15 + FFTSTAGE "FALSE","FALSE",fwd + M_END + + + M_START armSP_FFTInv_CToC_FC32_Radix4_ls_OutOfPlace,,d15 + FFTSTAGE "FALSE","TRUE",inv + M_END + + + .end diff --git a/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_s.S b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_s.S new file mode 100644 index 0000000..830fd16 --- /dev/null +++ b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix4_s.S @@ -0,0 +1,339 @@ +// +// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// +// This is a modification of armSP_FFT_CToC_SC32_Radix4_unsafe_s.s +// to support float instead of SC32. +// + +// +// Description: +// Compute a Radix 4 FFT stage for a N point complex signal +// +// + + +// Include standard headers + +#include "dl/api/arm/arm64COMM_s.h" +#include "dl/api/arm/omxtypes_s.h" + + +// Import symbols required from other files +// (For example tables) + + + + +// Set debugging level +//DEBUG_ON SETL {TRUE} + + + +// Guarding implementation by the processor name + + + + +// Guarding implementation by the processor name + + +// Import symbols required from other files +// (For example tables) + + +//Input Registers + +#define pSrc x0 +#define pDst x1 +#define pTwiddle x2 +#define pSubFFTNum x3 +#define pSubFFTSize x4 + + + +//Output Registers + + +//Local Scratch Registers + +#define subFFTNum x5 +#define subFFTSize x6 +#define grpCount x7 +#define grpCount32 w7 +#define pointStep x8 +#define pointStep32 w8 +#define outPointStep x9 +#define stepTwiddle x10 +#define setCount x11 +#define srcStep x12 +#define setStep x13 +#define dstStep x14 +#define twStep x15 + +// Neon Registers + +#define dW1 v0.2s +#define dW2 v1.2s +#define dW3 v2.2s + +#define dXr0 v4.2s +#define dXi0 v5.2s +#define dXr1 v6.2s +#define dXi1 v7.2s +#define dXr2 v8.2s +#define dXi2 v9.2s +#define dXr3 v10.2s +#define dXi3 v11.2s +#define dYr0 v12.2s +#define dYi0 v13.2s +#define dYr1 v14.2s +#define dYi1 v15.2s +#define dYr2 v16.2s +#define dYi2 v17.2s +#define dYr3 v18.2s +#define dYi3 v19.2s +#define dZr0 v20.2s +#define dZi0 v21.2s +#define dZr1 v22.2s +#define dZi1 v23.2s +#define dZr2 v24.2s +#define dZi2 v25.2s +#define dZr3 v26.2s +#define dZi3 v27.2s + + .MACRO FFTSTAGE scaled, inverse , name + + // Define stack arguments + + // Move args values into our work registers + ldr subFFTNum, [pSubFFTNum] + ldr subFFTSize, [pSubFFTSize] + + // Update grpCount and grpSize rightaway inorder to reuse + // pGrpCount and pGrpSize regs + + LSL grpCount,subFFTSize,#2 + LSR subFFTNum,subFFTNum,#2 + MOV subFFTSize,grpCount + + ld1 {dW1},[pTwiddle] //[wi | wr] + // pT0+1 increments pT0 by 8 bytes + // pT0+pointStep = increment of 8*pointStep bytes = 2*grpSize bytes + lsl pointStep,subFFTNum, #1 + + // pOut0+1 increments pOut0 by 8 bytes + // pOut0+outPointStep == increment of 8*outPointStep bytes + // = 2*size bytes + + MOV stepTwiddle,#0 + ld1 {dW2},[pTwiddle] //[wi | wr] + smull outPointStep,grpCount32,pointStep32 + + LSL pointStep,pointStep,#2 // 2*grpSize + + ld1 {dW3},[pTwiddle] //[wi | wr] + lsl srcStep,pointStep, #1 // srcStep = 2*pointStep + + ADD setStep,srcStep,pointStep // setStep = 3*pointStep + + rsb setStep,setStep,#0 // setStep = - 3*pointStep + SUB srcStep,srcStep,#16 // srcStep = 2*pointStep-16 + + lsl dstStep,outPointStep, #1 + + ADD dstStep,dstStep,outPointStep // dstStep = 3*outPointStep + // dstStep = - 3*outPointStep+16 + rsb dstStep,dstStep,#16 + + +radix4GrpLoop\name : + + ld2 {dXr0,dXi0},[pSrc],pointStep // data[0] + ADD stepTwiddle,stepTwiddle,pointStep + ld2 {dXr1,dXi1},[pSrc],pointStep // data[1] + // set pTwiddle to the first point + ADD pTwiddle,pTwiddle,stepTwiddle + ld2 {dXr2,dXi2},[pSrc],pointStep // data[2] + lsl twStep,stepTwiddle, #2 + + // data[3] & update pSrc for the next set + ld2 {dXr3,dXi3},[pSrc],setStep + SUB twStep,stepTwiddle,twStep // twStep = -3*stepTwiddle + + lsr setCount,pointStep, #3 + + // set pSrc to data[0] of the next set + ADD pSrc,pSrc,#16 + // increment to data[1] of the next set + ADD pSrc,pSrc,pointStep + + + // Loop on the sets + +radix4SetLoop\name : + + + + .ifeqs "\inverse", "TRUE" + fmul dZr1,dXr1,dW1[0] + fmul dZi1,dXi1,dW1[0] + fmul dZr2,dXr2,dW2[0] + fmul dZi2,dXi2,dW2[0] + fmul dZr3,dXr3,dW3[0] + fmul dZi3,dXi3,dW3[0] + + fmla dZr1,dXi1,dW1[1] // real part + fmls dZi1,dXr1,dW1[1] // imag part + + // data[1] for next iteration + ld2 {dXr1,dXi1},[pSrc],pointStep + + fmla dZr2,dXi2,dW2[1] // real part + fmls dZi2,dXr2,dW2[1] // imag part + + // data[2] for next iteration + ld2 {dXr2,dXi2},[pSrc],pointStep + + fmla dZr3,dXi3,dW3[1] // real part + fmls dZi3,dXr3,dW3[1] // imag part + .else + fmul dZr1,dXr1,dW1[0] + fmul dZi1,dXi1,dW1[0] + fmul dZr2,dXr2,dW2[0] + fmul dZi2,dXi2,dW2[0] + fmul dZr3,dXr3,dW3[0] + fmul dZi3,dXi3,dW3[0] + + fmls dZr1,dXi1,dW1[1] // real part + fmla dZi1,dXr1,dW1[1] // imag part + + // data[1] for next iteration + ld2 {dXr1,dXi1},[pSrc],pointStep + + fmls dZr2,dXi2,dW2[1] // real part + fmla dZi2,dXr2,dW2[1] // imag part + + // data[2] for next iteration + ld2 {dXr2,dXi2},[pSrc],pointStep + + fmls dZr3,dXi3,dW3[1] // real part + fmla dZi3,dXr3,dW3[1] // imag part + .endif + + // data[3] & update pSrc to data[0] + // But don't read on the very last iteration because that reads past + // the end of pSrc. The last iteration is grpCount = 4, setCount = 2. + cmp grpCount, #4 + + b.ne skipUpdate\name + cmp setCount, #2 + b.ne skipUpdate\name + add pSrc, pSrc, setStep + beq radix4SkipRead\name +skipUpdate\name: + ld2 {dXr3,dXi3},[pSrc],setStep +radix4SkipRead\name: + + SUBS setCount,setCount,#2 + + // finish first stage of 4 point FFT + // fadd qY0,qX0,qZ2 + // fsub qY2,qX0,qZ2 + fadd dYr0,dXr0,dZr2 + fsub dYr2,dXr0,dZr2 + fadd dYi0,dXi0,dZi2 + fsub dYi2,dXi0,dZi2 + + // data[0] for next iteration + ld2 {dXr0,dXi0},[pSrc], #16 + // fadd qY1,qZ1,qZ3 + // fsub qY3,qZ1,qZ3 + fadd dYr1,dZr1,dZr3 + fsub dYr3,dZr1,dZr3 + fadd dYi1,dZi1,dZi3 + fsub dYi3,dZi1,dZi3 + + // finish second stage of 4 point FFT + + // fsub qZ0,qY2,qY1 + fsub dZr0,dYr2,dYr1 + fsub dZi0,dYi2,dYi1 + + .ifeqs "\inverse", "TRUE" + + fadd dZr3,dYr0,dYi3 + st2 {dZr0,dZi0},[pDst],outPointStep + fsub dZi3,dYi0,dYr3 + + // fadd qZ2,qY2,qY1 + fadd dZr2,dYr2,dYr1 + fadd dZi2,dYi2,dYi1 + + st2 {dZr3,dZi3},[pDst],outPointStep + + fsub dZr1,dYr0,dYi3 + st2 {dZr2,dZi2},[pDst],outPointStep + fadd dZi1,dYi0,dYr3 + + st2 {dZr1,dZi1},[pDst],dstStep + + + .else + + fsub dZr1,dYr0,dYi3 + st2 {dZr0,dZi0},[pDst],outPointStep + fadd dZi1,dYi0,dYr3 + + // fadd qZ2,qY2,qY1 + fadd dZr2,dYr2,dYr1 + fadd dZi2,dYi2,dYi1 + + st2 {dZr1,dZi1},[pDst],outPointStep + + fadd dZr3,dYr0,dYi3 + st2 {dZr2,dZi2},[pDst],outPointStep + fsub dZi3,dYi0,dYr3 + + st2 {dZr3,dZi3},[pDst],dstStep + + + .endif + + // increment to data[1] of the next set + ADD pSrc,pSrc,pointStep + BGT radix4SetLoop\name + + + ld1 {dW1},[pTwiddle],stepTwiddle //[wi | wr] + // subtract 4 since grpCount multiplied by 4 + SUBS grpCount,grpCount,#4 + ld1 {dW2},[pTwiddle],stepTwiddle //[wi | wr] + // increment pSrc for the next grp + ADD pSrc,pSrc,srcStep + ld1 {dW3},[pTwiddle],twStep //[wi | wr] + BGT radix4GrpLoop\name + + str subFFTNum, [pSubFFTNum] + str subFFTSize, [pSubFFTSize] + + .endm + + + M_START armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace,,d15 + FFTSTAGE "FALSE","FALSE",FWD + M_END + + + M_START armSP_FFTInv_CToC_FC32_Radix4_OutOfPlace,,d15 + FFTSTAGE "FALSE","TRUE",INV + M_END + + + .end diff --git a/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix8_fs_s.S b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix8_fs_s.S new file mode 100644 index 0000000..f348e6a --- /dev/null +++ b/dl/sp/src/arm/arm64/armSP_FFT_CToC_FC32_Radix8_fs_s.S @@ -0,0 +1,473 @@ +// +// Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the LICENSE file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// +// This is a modification of armSP_FFT_CToC_FC32_Radix8_fs_unsafe_s.s +// to support float instead of SC32. +// + +// +// Description: +// Compute a first stage Radix 8 FFT stage for a N point complex signal +// +// + + +// Include standard headers + +#include "dl/api/arm/arm64COMM_s.h" +#include "dl/api/arm/omxtypes_s.h" + +// Import symbols required from other files +// (For example tables) + + +// Set debugging level +//DEBUG_ON SETL {TRUE} + + + +// Guarding implementation by the processor name + + + + +// Guarding implementation by the processor name + +//Input Registers + +#define pSrc x0 +#define pDst x1 +#define pTwiddle x2 +#define pSubFFTNum x3 +#define pSubFFTSize x4 + + +//Output Registers + + +//Local Scratch Registers + +#define subFFTNum x5 +#define subFFTSize x6 +#define grpSize x7 +// Reuse grpSize as setCount +#define setCount x7 +#define pointStep x8 +#define outPointStep x8 +#define setStep x9 +#define step1 x10 +#define step2 x11 +#define t0 w12 + + +// Neon Registers + +#define dXr0 v0.2s +#define dXi0 v1.2s +#define dXr1 v2.2s +#define dXi1 v3.2s +#define dXr2 v4.2s +#define dXi2 v5.2s +#define dXr3 v6.2s +#define dXi3 v7.2s +#define dXr4 v8.2s +#define dXi4 v9.2s +#define dXr5 v10.2s +#define dXi5 v11.2s +#define dXr6 v12.2s +#define dXi6 v13.2s +#define dXr7 v14.2s +#define dXi7 v15.2s +#define qX0 v0.4s +#define qX1 v1.4s +#define qX2 v2.4s +#define qX3 v3.4s +#define qX4 v4.4s +#define qX5 v5.4s +#define qX6 v6.4s +#define qX7 v7.4s + +#define dUr0 v16.2s +#define dUi0 v17.2s +#define dUr2 v18.2s +#define dUi2 v19.2s +#define dUr4 v20.2s +#define dUi4 v21.2s +#define dUr6 v22.2s +#define dUi6 v23.2s +#define dUr1 v24.2s +#define dUi1 v25.2s +#define dUr3 v26.2s +#define dUi3 v27.2s +#define dUr5 v28.2s +#define dUi5 v29.2s +// reuse dXr7 and dXi7 +#define dUr7 v30.2s +#define dUi7 v31.2s +#define qU0 v8.4s +#define qU1 v12.4s +#define qU2 v9.4s +#define qU3 v13.4s +#define qU4 v10.4s +#define qU5 v14.4s +#define qU6 v11.4s +#define qU7 v15.4s + + +#define dVr0 v24.2s +#define dVi0 v25.2s +#define dVr2 v26.2s +#define dVi2 v27.2s +#define dVr4 v28.2s +#define dVi4 v29.2s +#define dVr6 v30.2s +#define dVi6 v31.2s +#define dVr1 v16.2s +#define dVi1 v17.2s +#define dVr3 v18.2s +#define dVi3 v19.2s +#define dVr5 v20.2s +#define dVi5 v21.2s +#define dVr7 v22.2s +#define dVi7 v23.2s +#define qV0 v12.4s +#define qV1 v8.4s +#define qV2 v13.4s +#define qV3 v9.4s +#define qV4 v14.4s +#define qV5 v10.4s +#define qV6 v15.4s +#define qV7 v11.4s + +#define dYr0 v16.2s +#define dYi0 v17.2s +#define dYr2 v18.2s +#define dYi2 v19.2s +#define dYr4 v20.2s +#define dYi4 v21.2s +#define dYr6 v22.2s +#define dYi6 v23.2s +#define dYr1 v24.2s +#define dYi1 v25.2s +#define dYr3 v26.2s +#define dYi3 v27.2s +#define dYr5 v28.2s +#define dYi5 v29.2s +#define dYr7 v30.2s +#define dYi7 v31.2s +#define qY0 v8.4s +#define qY1 v12.4s +#define qY2 v9.4s +#define qY3 v13.4s +#define qY4 v10.4s +#define qY5 v14.4s +#define qY6 v11.4s +#define qY7 v15.4s + +#define dT0 v14.2s +#define dT0s v14.s +#define dT1 v15.2s + + .MACRO FFTSTAGE scaled, inverse, name + + // Define stack arguments + + // Move args values into our work registers + ldr subFFTNum, [pSubFFTNum] + ldr subFFTSize, [pSubFFTSize] + + // Update pSubFFTSize and pSubFFTNum regs + // subFFTSize = 1 for the first stage + + movz t0, 0x3f35, lsl #16 // High half word of sqrt(1/2). + movk t0, 0x04f3 // Low half word of sqrt(1/2). + MOV subFFTSize,#8 + + // Note: setCount = subFFTNum/8 (reuse the grpSize reg for setCount) + LSR grpSize,subFFTNum,#3 + MOV subFFTNum,grpSize + + + // pT0+1 increments pT0 by 8 bytes + // pT0+pointStep = increment of 8*pointStep bytes = grpSize bytes + // Note: outPointStep = pointStep for firststage + + lsl pointStep,grpSize, #3 + + + // Calculate the step of input data for the next set + //MOV step1,pointStep,LSL #1 // step1 = 2*pointStep + ld2 {dXr0,dXi0},[pSrc],pointStep // data[0] + lsl step1,grpSize, #4 + lsl step2,pointStep, #3 + + ld2 {dXr1,dXi1},[pSrc],pointStep // data[1] + SUB step2,step2,pointStep // step2 = 7*pointStep + // setStep = - 7*pointStep+16 + rsb setStep,step2,#16 + + ld2 {dXr2,dXi2},[pSrc],pointStep // data[2] + ld2 {dXr3,dXi3},[pSrc],pointStep // data[3] + ld2 {dXr4,dXi4},[pSrc],pointStep // data[4] + ld2 {dXr5,dXi5},[pSrc],pointStep // data[5] + ld2 {dXr6,dXi6},[pSrc],pointStep // data[6] + // data[7] & update pSrc for the next set + // setStep = -7*pointStep + 16 + ld2 {dXr7,dXi7},[pSrc],setStep + // grp = 0 a special case since all the twiddle factors are 1 + // Loop on the sets + +radix8fsGrpZeroSetLoop\name : + + // Decrement setcount + SUBS setCount,setCount,#2 + + + // finish first stage of 8 point FFT + + // fadd qU0,qX0,qX4 + // fadd qU2,qX1,qX5 + // fadd qU4,qX2,qX6 + // fadd qU6,qX3,qX7 + fadd dUr0,dXr0,dXr4 + fadd dUr2,dXr1,dXr5 + fadd dUr4,dXr2,dXr6 + fadd dUr6,dXr3,dXr7 + fadd dUi0,dXi0,dXi4 + fadd dUi2,dXi1,dXi5 + fadd dUi4,dXi2,dXi6 + fadd dUi6,dXi3,dXi7 + + // finish second stage of 8 point FFT + + // fadd qV0,qU0,qU4 + // fsub qV2,qU0,qU4 + // fadd qV4,qU2,qU6 + // fsub qV6,qU2,qU6 + fadd dVr0,dUr0,dUr4 + fsub dVr2,dUr0,dUr4 + fadd dVr4,dUr2,dUr6 + fsub dVr6,dUr2,dUr6 + fadd dVi0,dUi0,dUi4 + fsub dVi2,dUi0,dUi4 + fadd dVi4,dUi2,dUi6 + fsub dVi6,dUi2,dUi6 + + // finish third stage of 8 point FFT + + // fadd qY0,qV0,qV4 + // fsub qY4,qV0,qV4 + fadd dYr0,dVr0,dVr4 + fsub dYr4,dVr0,dVr4 + fadd dYi0,dVi0,dVi4 + fsub dYi4,dVi0,dVi4 + + st2 {dYr0,dYi0},[pDst],step1 // store y0 + + .ifeqs "\inverse", "TRUE" + + fsub dYr2,dVr2,dVi6 + fadd dYi2,dVi2,dVr6 + + fadd dYr6,dVr2,dVi6 + st2 {dYr2,dYi2},[pDst],step1 // store y2 + fsub dYi6,dVi2,dVr6 + + // fsub qU1,qX0,qX4 + fsub dUr1,dXr0,dXr4 + fsub dUi1,dXi0,dXi4 + + st2 {dYr4,dYi4},[pDst],step1 // store y4 + + // fsub qU3,qX1,qX5 + // fsub qU5,qX2,qX6 + fsub dUr3,dXr1,dXr5 + fsub dUr5,dXr2,dXr6 + fsub dUi3,dXi1,dXi5 + fsub dUi5,dXi2,dXi6 + + st2 {dYr6,dYi6},[pDst],step1 // store y6 + + .ELSE + + fadd dYr6,dVr2,dVi6 + fsub dYi6,dVi2,dVr6 + + fsub dYr2,dVr2,dVi6 + st2 {dYr6,dYi6},[pDst],step1 // store y2 + fadd dYi2,dVi2,dVr6 + + + // fsub qU1,qX0,qX4 + fsub dUr1,dXr0,dXr4 + fsub dUi1,dXi0,dXi4 + + st2 {dYr4,dYi4},[pDst],step1 // store y4 + + // fsub qU3,qX1,qX5 + // fsub qU5,qX2,qX6 + fsub dUr3,dXr1,dXr5 + fsub dUr5,dXr2,dXr6 + fsub dUi3,dXi1,dXi5 + fsub dUi5,dXi2,dXi6 + + st2 {dYr2,dYi2},[pDst],step1 // store y6 + + + .ENDIF + + // finish first stage of 8 point FFT + + // fsub qU7,qX3,qX7 + fsub dUr7,dXr3,dXr7 + fsub dUi7,dXi3,dXi7 + + mov dT0s[0], t0 + + // finish second stage of 8 point FFT + + fsub dVr1,dUr1,dUi5 + // data[0] for next iteration + ld2 {dXr0,dXi0},[pSrc],pointStep + fadd dVi1,dUi1,dUr5 + fadd dVr3,dUr1,dUi5 + ld2 {dXr1,dXi1},[pSrc],pointStep // data[1] + fsub dVi3,dUi1,dUr5 + + fsub dVr5,dUr3,dUi7 + ld2 {dXr2,dXi2},[pSrc],pointStep // data[2] + fadd dVi5,dUi3,dUr7 + fadd dVr7,dUr3,dUi7 + ld2 {dXr3,dXi3},[pSrc],pointStep // data[3] + fsub dVi7,dUi3,dUr7 + + // finish third stage of 8 point FFT + + .ifeqs "\inverse", "TRUE" + + // calculate a*v5 + fmul dT1,dVr5,dT0[0] // use dVi0 for dT1 + + ld2 {dXr4,dXi4},[pSrc],pointStep // data[4] + fmul dVi5,dVi5,dT0[0] + + ld2 {dXr5,dXi5},[pSrc],pointStep // data[5] + fsub dVr5,dT1,dVi5 // a * V5 + fadd dVi5,dT1,dVi5 + + ld2 {dXr6,dXi6},[pSrc],pointStep // data[6] + + // calculate b*v7 + fmul dT1,dVr7,dT0[0] + fmul dVi7,dVi7,dT0[0] + + // fadd qY1,qV1,qV5 + // fsub qY5,qV1,qV5 + fadd dYr1,dVr1,dVr5 + fsub dYr5,dVr1,dVr5 + fadd dYi1,dVi1,dVi5 + fsub dYi5,dVi1,dVi5 + + fadd dVr7,dT1,dVi7 // b * V7 + fsub dVi7,dVi7,dT1 + SUB pDst, pDst, step2 // set pDst to y1 + + // On the last iteration, this will read past the end of pSrc, + // so skip this read. + BEQ radix8SkipLastUpdateInv\name + ld2 {dXr7,dXi7},[pSrc],setStep // data[7] +radix8SkipLastUpdateInv\name: + + fsub dYr3,dVr3,dVr7 + fsub dYi3,dVi3,dVi7 + st2 {dYr1,dYi1},[pDst],step1 // store y1 + fadd dYr7,dVr3,dVr7 + fadd dYi7,dVi3,dVi7 + + + st2 {dYr3,dYi3},[pDst],step1 // store y3 + st2 {dYr5,dYi5},[pDst],step1 // store y5 + st2 {dYr7,dYi7},[pDst] // store y7 + ADD pDst, pDst, #16 + + .ELSE + + // calculate b*v7 + fmul dT1,dVr7,dT0[0] + ld2 {dXr4,dXi4},[pSrc],pointStep // data[4] + fmul dVi7,dVi7,dT0[0] + + ld2 {dXr5,dXi5},[pSrc],pointStep // data[5] + fadd dVr7,dT1,dVi7 // b * V7 + fsub dVi7,dVi7,dT1 + + ld2 {dXr6,dXi6},[pSrc],pointStep // data[6] + + // calculate a*v5 + fmul dT1,dVr5,dT0[0] // use dVi0 for dT1 + fmul dVi5,dVi5,dT0[0] + + fadd dYr7,dVr3,dVr7 + fadd dYi7,dVi3,dVi7 + SUB pDst, pDst, step2 // set pDst to y1 + + fsub dVr5,dT1,dVi5 // a * V5 + fadd dVi5,dT1,dVi5 + + // On the last iteration, this will read past the end of pSrc, + // so skip this read. + BEQ radix8SkipLastUpdateFwd\name + ld2 {dXr7,dXi7},[pSrc],setStep // data[7] +radix8SkipLastUpdateFwd\name: + + // fsub qY5,qV1,qV5 + fsub dYr5,dVr1,dVr5 + fsub dYi5,dVi1,dVi5 + + fsub dYr3,dVr3,dVr7 + st2 {dYr7,dYi7},[pDst],step1 // store y1 + fsub dYi3,dVi3,dVi7 + + // fadd qY1,qV1,qV5 + fadd dYr1,dVr1,dVr5 + fadd dYi1,dVi1,dVi5 + + st2 {dYr5,dYi5},[pDst],step1 // store y3 + st2 {dYr3,dYi3},[pDst],step1 // store y5 + st2 {dYr1,dYi1},[pDst],#16 // store y7 + + .ENDIF + + + // update pDst for the next set + SUB pDst, pDst, step2 + BGT radix8fsGrpZeroSetLoop\name + + // Save subFFTNum and subFFTSize for next stage + str subFFTNum, [pSubFFTNum] + str subFFTSize, [pSubFFTSize] + + .endm + + + // Allocate stack memory required by the function + + + M_START armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace,,d15 + FFTSTAGE "FALSE","FALSE",FWD + M_END + + + M_START armSP_FFTInv_CToC_FC32_Radix8_fs_OutOfPlace,,d15 + FFTSTAGE "FALSE","TRUE",INV + M_END + + + + .end diff --git a/dl/sp/src/arm/arm64/omxSP_FFTFwd_CToC_FC32.c b/dl/sp/src/arm/arm64/omxSP_FFTFwd_CToC_FC32.c new file mode 100644 index 0000000..f29796b --- /dev/null +++ b/dl/sp/src/arm/arm64/omxSP_FFTFwd_CToC_FC32.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/armSP.h" +#include "dl/sp/api/omxSP.h" + +extern void armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +/** + * Function: omxSP_FFTFwd_CToC_FC32_Sfs (2.2.4.2.2) + * + * Description: + * Compute an FFT for a complex signal of length of 2^order, + * where 0 <= order <= 15. + * Transform length is determined by the specification structure, which + * must be initialized prior to calling the FFT function using the appropriate + * helper, i.e., <FFTInit_C_sc32> or <FFTInit_C_SC16>. The relationship + * between the input and output sequences can be expressed in terms of the + * DFT, i.e., + * + * X[k] = SUM[n=0...N-1]x[n].e^(-jnk.2.pi/N) + * k = 0,1,2,..., N-1 + * N = 2^order + * + * Input Arguments: + * pSrc - pointer to the input signal, a complex-valued vector of length + * 2^order; must be aligned on a 32 byte boundary. + * pFFTSpec - pointer to the preallocated and initialized specification + * structure + * + * Output Arguments: + * pDst - pointer to the complex-valued output vector, of length 2^order; + * must be aligned on an 32-byte boundary. + * + * Return Value: + * + * OMX_Sts_NoErr - no error + * OMX_Sts_BadArgErr - returned if one or more of the following conditions + * is true: + * - one or more of the following pointers is NULL: pSrc, pDst, or + * pFFTSpec. + * - pSrc or pDst is not 32-byte aligned + * + */ + +OMXResult omxSP_FFTFwd_CToC_FC32_Sfs(const OMX_FC32* pSrc, + OMX_FC32* pDst, + const OMXFFTSpec_C_FC32* pFFTSpec) { + ARMsFFTSpec_FC32* spec = (ARMsFFTSpec_FC32*)pFFTSpec; + int order; + long subFFTSize; + long subFFTNum; + OMX_FC32* pTwiddle; + OMX_FC32* pOut; + + /* + * Check args are not NULL and the source and destination pointers + * are properly aligned. + */ + if (!validateParametersFC32(pSrc, pDst, spec)) + return OMX_Sts_BadArgErr; + + order = fastlog2(spec->N); + + subFFTSize = 1; + subFFTNum = spec->N; + pTwiddle = spec->pTwiddle; + pOut = spec->pBuf; + + if (order > 3) { + OMX_FC32* argDst; + + /* + * Set up argDst and pOut appropriately so that pOut = pDst for + * the very last FFT stage. + */ + if ((order & 2) == 0) { + argDst = pOut; + pOut = pDst; + } else { + argDst = pDst; + } + + /* + * Odd order uses a radix 8 first stage; even order, a radix 4 + * first stage. + */ + if (order & 1) { + armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace( + pSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); + } else { + armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace( + pSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); + } + + /* + * Now use radix 4 stages to finish rest of the FFT + */ + if (subFFTNum >= 4) { + while (subFFTNum > 4) { + OMX_FC32* tmp; + + armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace( + argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + /* + * Swap argDst and pOut + */ + tmp = pOut; + pOut = argDst; + argDst = tmp; + } + + armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace( + argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + } + } else if (order == 3) { + armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( + pSrc, pDst, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace( + pDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace( + pOut, pDst, pTwiddle, &subFFTNum, &subFFTSize); + } else if (order == 2) { + armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( + pSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace( + pOut, pDst, pTwiddle, &subFFTNum, &subFFTSize); + } else { + /* Order = 1 */ + armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( + pSrc, pDst, pTwiddle, &subFFTNum, &subFFTSize); + } + + return OMX_Sts_NoErr; +} diff --git a/dl/sp/src/arm/arm64/omxSP_FFTFwd_RToCCS_F32.c b/dl/sp/src/arm/arm64/omxSP_FFTFwd_RToCCS_F32.c new file mode 100644 index 0000000..f1e503e --- /dev/null +++ b/dl/sp/src/arm/arm64/omxSP_FFTFwd_RToCCS_F32.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/armSP.h" +#include "dl/sp/api/omxSP.h" + +extern void armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void ComplexToRealFixup(OMX_FC32* pSrc, + OMX_F32* pDst, + const OMX_FC32* pTwiddle, + OMX_F32* pBuf, + long N); + +/** + * Function: omxSP_FFTFwd_CToC_FC32_Sfs (2.2.4.2.2) + * + * Description: + * Compute an FFT for a complex signal of length of 2^order, + * where 0 <= order <= 15. + * Transform length is determined by the specification structure, which + * must be initialized prior to calling the FFT function using the appropriate + * helper, i.e., <FFTInit_C_sc32> or <FFTInit_C_SC16>. The relationship + * between the input and output sequences can be expressed in terms of the + * DFT, i.e., + * + * X[k] = SUM[n=0...N-1]x[n].e^(-jnk.2.pi/N) + * k = 0,1,2,..., N-1 + * N = 2^order + * + * Input Arguments: + * pSrc - pointer to the input signal, a complex-valued vector of length + * 2^order; must be aligned on a 32 byte boundary. + * pFFTSpec - pointer to the preallocated and initialized specification + * structure + * + * Output Arguments: + * pDst - pointer to the complex-valued output vector, of length 2^order; + * must be aligned on an 32-byte boundary. + * + * Return Value: + * + * OMX_Sts_NoErr - no error + * OMX_Sts_BadArgErr - returned if one or more of the following conditions + * is true: + * - one or more of the following pointers is NULL: pSrc, pDst, or + * pFFTSpec. + * - pSrc or pDst is not 32-byte aligned + * + */ + +OMXResult omxSP_FFTFwd_RToCCS_F32_Sfs(const OMX_F32* pSrc, + OMX_F32* pDst, + const OMXFFTSpec_R_F32* pFFTSpec) { + ARMsFFTSpec_R_FC32* spec = (ARMsFFTSpec_R_FC32*)pFFTSpec; + int order; + long subFFTSize; + long subFFTNum; + OMX_FC32* pTwiddle; + OMX_FC32* pOut; + OMX_FC32* pComplexSrc = (OMX_FC32*) pSrc; + OMX_FC32* pComplexDst = (OMX_FC32*) pDst; + + /* + * Check args are not NULL and the source and destination pointers + * are properly aligned. + */ + if (!validateParametersF32(pSrc, pDst, spec)) + return OMX_Sts_BadArgErr; + + /* + * Compute the RFFT using a complex FFT of one less order, so set + * order to be the order of the complex FFT. + */ + order = fastlog2(spec->N) - 1; + + subFFTSize = 1; + subFFTNum = spec->N >> 1; + pTwiddle = spec->pTwiddle; + pOut = (OMX_FC32*) spec->pBuf; + + if (order > 3) { + OMX_FC32* argDst; + OMX_FC32* pComplexDst = (OMX_FC32*) pDst; + + /* + * Set up argDst and pOut appropriately so that pOut = pDst for + * ComplexToRealFixup. + */ + if ((order & 2) != 0) { + argDst = pOut; + pOut = pComplexDst; + } else { + argDst = pComplexDst; + } + + /* + * Odd order uses a radix 8 first stage; even order, a radix 4 + * first stage. + */ + if (order & 1) { + armSP_FFTFwd_CToC_FC32_Radix8_fs_OutOfPlace( + pComplexSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); + } else { + armSP_FFTFwd_CToC_FC32_Radix4_fs_OutOfPlace( + pComplexSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); + } + + /* + * Now use radix 4 stages to finish rest of the FFT + */ + if (subFFTNum >= 4) { + while (subFFTNum > 4) { + OMX_FC32* tmp; + + armSP_FFTFwd_CToC_FC32_Radix4_OutOfPlace( + argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + /* + * Swap argDst and pOut + */ + tmp = pOut; + pOut = argDst; + argDst = tmp; + } + + armSP_FFTFwd_CToC_FC32_Radix4_ls_OutOfPlace( + argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + } + } else if (order == 3) { + armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( + pComplexSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTFwd_CToC_FC32_Radix2_OutOfPlace( + pOut, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace( + pComplexDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + } else if (order == 2) { + armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( + pComplexSrc, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTFwd_CToC_FC32_Radix2_ls_OutOfPlace( + pComplexDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + } else if (order == 1) { + armSP_FFTFwd_CToC_FC32_Radix2_fs_OutOfPlace( + pComplexSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize); + } else { + /* Handle complex order 0 specially */ + pOut->Re = pSrc[0]; + pOut->Im = pSrc[1]; + } + + /* + * Complex FFT done. Fix up the complex result to give the correct + * RFFT. + */ + + ComplexToRealFixup(pOut, pDst, pTwiddle, spec->pBuf, spec->N); + + return OMX_Sts_NoErr; +} diff --git a/dl/sp/src/arm/arm64/omxSP_FFTInv_CCSToR_F32.c b/dl/sp/src/arm/arm64/omxSP_FFTInv_CCSToR_F32.c new file mode 100644 index 0000000..84de9cf --- /dev/null +++ b/dl/sp/src/arm/arm64/omxSP_FFTInv_CCSToR_F32.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <arm_neon.h> + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/armSP.h" +#include "dl/sp/api/omxSP.h" + +extern void armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix2_ls_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix2_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix4_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix4_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix4_ls_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix8_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CCSToR_F32_preTwiddleRadix2( + const OMX_F32* pSrc, + const OMX_FC32* pTwiddle, + OMX_F32* pBuf, + long N); + +/* + * Scale FFT data by 1/|length|. |length| must be a power of two + */ +static inline ScaleRFFTData(OMX_F32* fftData, unsigned length) { + float32_t* data = (float32_t*)fftData; + float32_t scale = 2.0f / length; + + if (length >= 4) { + /* + * Do 4 float elements at a time because |length| is always a + * multiple of 4 when |length| >= 4. + * + * TODO(rtoy): Figure out how to process 8 elements at a time + * using intrinsics or replace this with inline assembly. + */ + do { + float32x4_t x = vld1q_f32(data); + + length -= 4; + x = vmulq_n_f32(x, scale); + vst1q_f32(data, x); + data += 4; + } while (length > 0); + } else if (length == 2) { + float32x2_t x = vld1_f32(data); + x = vmul_n_f32(x, scale); + vst1_f32(data, x); + } else { + fftData[0] *= scale; + } +} + +/** + * Function: omxSP_FFTInv_CCSToR_F32_Sfs + * + * Description: + * These functions compute the inverse FFT for a conjugate-symmetric input + * sequence. Transform length is determined by the specification structure, + * which must be initialized prior to calling the FFT function using + * <FFTInit_R_F32>. For a transform of length M, the input sequence is + * represented using a packed CCS vector of length M+2, and is organized + * as follows: + * + * Index: 0 1 2 3 4 5 . . . M-2 M-1 M M+1 + * Comp: R[0] 0 R[1] I[1] R[2] I[2] . . . R[M/2-1] I[M/2-1] R[M/2] 0 + * + * where R[n] and I[n], respectively, denote the real and imaginary + * components for FFT bin n. Bins are numbered from 0 to M/2, where M + * is the FFT length. Bin index 0 corresponds to the DC component, + * and bin index M/2 corresponds to the foldover frequency. + * + * Input Arguments: + * pSrc - pointer to the complex-valued input sequence represented + * using CCS format, of length (2^order) + 2; must be aligned on a + * 32-byte boundary. + * pFFTSpec - pointer to the preallocated and initialized + * specification structure + * + * Output Arguments: + * pDst - pointer to the real-valued output sequence, of length + * 2^order ; must be aligned on a 32-byte boundary. + * + * Return Value: + * + * OMX_Sts_NoErr - no error + + * OMX_Sts_BadArgErr - bad arguments if one or more of the + * following is true: + * - pSrc, pDst, or pFFTSpec is NULL + * - pSrc or pDst is not aligned on a 32-byte boundary + * + */ +OMXResult omxSP_FFTInv_CCSToR_F32_Sfs( + const OMX_F32* pSrc, + OMX_F32* pDst, + const OMXFFTSpec_R_F32* pFFTSpec) { + ARMsFFTSpec_R_FC32* spec = (ARMsFFTSpec_R_FC32*)pFFTSpec; + int order; + long subFFTSize; + long subFFTNum; + OMX_FC32* pTwiddle; + OMX_FC32* pOut; + OMX_FC32* pComplexSrc; + OMX_FC32* pComplexDst = (OMX_FC32*) pDst; + + /* + * Check args are not NULL and the source and destination pointers + * are properly aligned. + */ + if (!validateParametersF32(pSrc, pDst, spec)) + return OMX_Sts_BadArgErr; + + /* + * Preprocess the input before calling the complex inverse FFT. The + * result is actually stored in the second half of the temp buffer + * in pFFTSpec. + */ + if (spec->N > 1) + armSP_FFTInv_CCSToR_F32_preTwiddleRadix2( + pSrc, spec->pTwiddle, spec->pBuf, spec->N); + + /* + * Do a complex inverse FFT of half size. + */ + order = fastlog2(spec->N) - 1; + + subFFTSize = 1; + subFFTNum = spec->N >> 1; + pTwiddle = spec->pTwiddle; + /* + * The pBuf is split in half. The first half is the temp buffer. The + * second half holds the source data that was placed there by + * armSP_FFTInv_CCSToR_F32_preTwiddleRadix2_unsafe. + */ + pOut = (OMX_FC32*) spec->pBuf; + pComplexSrc = pOut + (1 << order); + + + if (order > 3) { + OMX_FC32* argDst; + + /* + * Set up argDst and pOut appropriately so that pOut = pDst for + * the very last FFT stage. + */ + if ((order & 2) == 0) { + argDst = pOut; + pOut = pComplexDst; + } else { + argDst = pComplexDst; + } + + /* + * Odd order uses a radix 8 first stage; even order, a radix 4 + * first stage. + */ + if (order & 1) { + armSP_FFTInv_CToC_FC32_Radix8_fs_OutOfPlace( + pComplexSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); + } else { + armSP_FFTInv_CToC_FC32_Radix4_fs_OutOfPlace( + pComplexSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); + } + + /* + * Now use radix 4 stages to finish rest of the FFT + */ + if (subFFTNum >= 4) { + while (subFFTNum > 4) { + OMX_FC32* tmp; + + armSP_FFTInv_CToC_FC32_Radix4_OutOfPlace( + argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + /* + * Swap argDst and pOut + */ + tmp = pOut; + pOut = argDst; + argDst = tmp; + } + + armSP_FFTInv_CToC_FC32_Radix4_ls_OutOfPlace( + argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + } + } else if (order == 3) { + armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace( + pComplexSrc, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTInv_CToC_FC32_Radix2_OutOfPlace( + pComplexDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTInv_CToC_FC32_Radix2_ls_OutOfPlace( + pOut, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); + } else if (order == 2) { + armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace( + pComplexSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTInv_CToC_FC32_Radix2_ls_OutOfPlace( + pOut, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); + } else if (order == 1) { + armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace( + pComplexSrc, pComplexDst, pTwiddle, &subFFTNum, &subFFTSize); + } else { + /* Order = 0 */ + *pComplexDst = *pComplexSrc; + } + + ScaleRFFTData(pDst, spec->N); + return OMX_Sts_NoErr; +} + diff --git a/dl/sp/src/arm/arm64/omxSP_FFTInv_CToC_FC32.c b/dl/sp/src/arm/arm64/omxSP_FFTInv_CToC_FC32.c new file mode 100644 index 0000000..eec05e9 --- /dev/null +++ b/dl/sp/src/arm/arm64/omxSP_FFTInv_CToC_FC32.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include <arm_neon.h> + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/armSP.h" +#include "dl/sp/api/omxSP.h" + +extern void armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix2_ls_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix2_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix4_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix4_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix4_ls_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +extern void armSP_FFTInv_CToC_FC32_Radix8_fs_OutOfPlace( + const OMX_FC32* pSrc, + OMX_FC32* pDst, + OMX_FC32* pTwiddle, + long* subFFTNum, + long* subFFTSize); + +/* + * Scale FFT data by 1/|length|. |length| must be a power of two + */ +static inline ScaleFFTData(OMX_FC32* fftData, unsigned length) { + float32_t* data = (float32_t*)fftData; + float32_t scale = 1.0f / length; + + /* + * Do two complex elements at a time because |length| is always + * greater than or equal to 2 (order >= 1) + */ + do { + float32x4_t x = vld1q_f32(data); + + length -= 2; + x = vmulq_n_f32(x, scale); + vst1q_f32(data, x); + data += 4; + } while (length > 0); +} + +/** + * Function: omxSP_FFTInv_CToC_FC32 + * + * Description: + * These functions compute an inverse FFT for a complex signal of + * length of 2^order, where 0 <= order <= 15. Transform length is + * determined by the specification structure, which must be + * initialized prior to calling the FFT function using the appropriate + * helper, i.e., <FFTInit_C_FC32>. The relationship between the input + * and output sequences can be expressed in terms of the IDFT, i.e.: + * + * x[n] = SUM[k=0,...,N-1] X[k].e^(jnk.2.pi/N) + * n=0,1,2,...N-1 + * N=2^order. + * + * Input Arguments: + * pSrc - pointer to the complex-valued input signal, of length 2^order ; + * must be aligned on a 32-byte boundary. + * pFFTSpec - pointer to the preallocated and initialized specification + * structure + * + * Output Arguments: + * order + * pDst - pointer to the complex-valued output signal, of length 2^order; + * must be aligned on a 32-byte boundary. + * + * Return Value: + * + * OMX_Sts_NoErr - no error + * OMX_Sts_BadArgErr - returned if one or more of the following conditions + * is true: + * - one or more of the following pointers is NULL: pSrc, pDst, or + * pFFTSpec. + * - pSrc or pDst is not 32-byte aligned + * + */ + +OMXResult omxSP_FFTInv_CToC_FC32_Sfs(const OMX_FC32* pSrc, + OMX_FC32* pDst, + const OMXFFTSpec_C_FC32* pFFTSpec) { + ARMsFFTSpec_FC32* spec = (ARMsFFTSpec_FC32*)pFFTSpec; + int order; + long subFFTSize; + long subFFTNum; + OMX_FC32* pTwiddle; + OMX_FC32* pOut; + + /* + * Check args are not NULL and the source and destination pointers + * are properly aligned. + */ + if (!validateParametersFC32(pSrc, pDst, spec)) + return OMX_Sts_BadArgErr; + + order = fastlog2(spec->N); + + subFFTSize = 1; + subFFTNum = spec->N; + pTwiddle = spec->pTwiddle; + pOut = spec->pBuf; + + if (order > 3) { + OMX_FC32* argDst; + + /* + * Set up argDst and pOut appropriately so that pOut = pDst for + * the very last FFT stage. + */ + if ((order & 2) == 0) { + argDst = pOut; + pOut = pDst; + } else { + argDst = pDst; + } + + /* + * Odd order uses a radix 8 first stage; even order, a radix 4 + * first stage. + */ + if (order & 1) { + armSP_FFTInv_CToC_FC32_Radix8_fs_OutOfPlace( + pSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); + } else { + armSP_FFTInv_CToC_FC32_Radix4_fs_OutOfPlace( + pSrc, argDst, pTwiddle, &subFFTNum, &subFFTSize); + } + + /* + * Now use radix 4 stages to finish rest of the FFT + */ + if (subFFTNum >= 4) { + while (subFFTNum > 4) { + OMX_FC32* tmp; + + armSP_FFTInv_CToC_FC32_Radix4_OutOfPlace( + argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + /* + * Swap argDst and pOut + */ + tmp = pOut; + pOut = argDst; + argDst = tmp; + } + + armSP_FFTInv_CToC_FC32_Radix4_ls_OutOfPlace( + argDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + } + } else if (order == 3) { + armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace( + pSrc, pDst, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTInv_CToC_FC32_Radix2_OutOfPlace( + pDst, pOut, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTInv_CToC_FC32_Radix2_ls_OutOfPlace( + pOut, pDst, pTwiddle, &subFFTNum, &subFFTSize); + } else if (order == 2) { + armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace( + pSrc, pOut, pTwiddle, &subFFTNum, &subFFTSize); + armSP_FFTInv_CToC_FC32_Radix2_ls_OutOfPlace( + pOut, pDst, pTwiddle, &subFFTNum, &subFFTSize); + } else { + /* Order = 1 */ + armSP_FFTInv_CToC_FC32_Radix2_fs_OutOfPlace( + pSrc, pDst, pTwiddle, &subFFTNum, &subFFTSize); + } + + ScaleFFTData(pDst, spec->N); + return OMX_Sts_NoErr; +} diff --git a/dl/sp/src/mips/mips_FFTFwd_RToCCS_F32_complex.c b/dl/sp/src/mips/mips_FFTFwd_RToCCS_F32_complex.c new file mode 100644 index 0000000..f5a8a19 --- /dev/null +++ b/dl/sp/src/mips/mips_FFTFwd_RToCCS_F32_complex.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#include <stdint.h> + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/mipsSP.h" + +/* + * Forward real FFT for FFT sizes larger than 16. Computed using the complex + * FFT for half the size. + */ +OMXResult mips_FFTFwd_RToCCS_F32_complex(const OMX_F32* pSrc, + OMX_F32* pDst, + const MIPSFFTSpec_R_FC32* pFFTSpec) { + OMX_U32 n1_4, num_transforms, step; + OMX_F32* w_re_ptr; + OMX_F32* w_im_ptr; + OMX_U32 fft_size = 1 << pFFTSpec->order; + OMX_FC32* p_dst = (OMX_FC32*)pDst; + OMX_FC32* p_buf = (OMX_FC32*)pFFTSpec->pBuf; + OMX_F32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; + OMX_F32 w_re, w_im; + + /* + * Loop performing sub-transforms of size 4, + * which contain 2 butterfly operations. + */ + num_transforms = (SUBTRANSFORM_CONST >> (17 - pFFTSpec->order)) | 1; + for (uint32_t n = 0; n < num_transforms; ++n) { + /* + * n is in the range (0 .. num_transforms - 1). + * The size of the pFFTSpec->pOffset is (((SUBTRANSFORM_CONST >> + * (16 - TWIDDLE_TABLE_ORDER)) | 1)). + */ + OMX_U32 offset = pFFTSpec->pOffset[n] << 2; + /* + * Offset takes it's value from pFFTSpec->pOffset table which is initialized + * in the omxSP_FFTInit_R_F32 function, and is constant afterwards. + */ + OMX_U16* p_bitrev = pFFTSpec->pBitRev + offset; + OMX_FC32* p_tmp = p_buf + offset; + /* Treating the input as a complex vector. */ + const OMX_FC32* p_src = (const OMX_FC32*)pSrc; + + tmp1 = p_src[p_bitrev[0]].Re + p_src[p_bitrev[1]].Re; + tmp2 = p_src[p_bitrev[2]].Re + p_src[p_bitrev[3]].Re; + tmp3 = p_src[p_bitrev[0]].Im + p_src[p_bitrev[1]].Im; + tmp4 = p_src[p_bitrev[2]].Im + p_src[p_bitrev[3]].Im; + + p_tmp[0].Re = tmp1 + tmp2; + p_tmp[2].Re = tmp1 - tmp2; + p_tmp[0].Im = tmp3 + tmp4; + p_tmp[2].Im = tmp3 - tmp4; + + tmp1 = p_src[p_bitrev[0]].Re - p_src[p_bitrev[1]].Re; + tmp2 = p_src[p_bitrev[2]].Re - p_src[p_bitrev[3]].Re; + tmp3 = p_src[p_bitrev[0]].Im - p_src[p_bitrev[1]].Im; + tmp4 = p_src[p_bitrev[2]].Im - p_src[p_bitrev[3]].Im; + + p_tmp[1].Re = tmp1 + tmp4; + p_tmp[3].Re = tmp1 - tmp4; + p_tmp[1].Im = tmp3 - tmp2; + p_tmp[3].Im = tmp3 + tmp2; + } + + /* + * Loop performing sub-transforms of size 8, + * which contain four butterfly operations. + */ + num_transforms = (num_transforms >> 1) | 1; + for (uint32_t n = 0; n < num_transforms; ++n) { + OMX_U32 offset = pFFTSpec->pOffset[n] << 3; + OMX_U16* p_bitrev = pFFTSpec->pBitRev + offset; + OMX_FC32* p_tmp = p_buf + offset; + const OMX_FC32* p_src = (const OMX_FC32*)pSrc; + + tmp1 = p_src[p_bitrev[4]].Re + p_src[p_bitrev[5]].Re; + tmp2 = p_src[p_bitrev[6]].Re + p_src[p_bitrev[7]].Re; + tmp3 = p_src[p_bitrev[4]].Im + p_src[p_bitrev[5]].Im; + tmp4 = p_src[p_bitrev[6]].Im + p_src[p_bitrev[7]].Im; + + tmp5 = tmp1 + tmp2; + tmp1 = tmp1 - tmp2; + tmp2 = tmp3 + tmp4; + tmp3 = tmp3 - tmp4; + + p_tmp[4].Re = p_tmp[0].Re - tmp5; + p_tmp[0].Re = p_tmp[0].Re + tmp5; + p_tmp[4].Im = p_tmp[0].Im - tmp2; + p_tmp[0].Im = p_tmp[0].Im + tmp2; + p_tmp[6].Re = p_tmp[2].Re - tmp3; + p_tmp[2].Re = p_tmp[2].Re + tmp3; + p_tmp[6].Im = p_tmp[2].Im + tmp1; + p_tmp[2].Im = p_tmp[2].Im - tmp1; + + tmp1 = p_src[p_bitrev[4]].Re - p_src[p_bitrev[5]].Re; + tmp2 = p_src[p_bitrev[6]].Re - p_src[p_bitrev[7]].Re; + tmp3 = p_src[p_bitrev[4]].Im - p_src[p_bitrev[5]].Im; + tmp4 = p_src[p_bitrev[6]].Im - p_src[p_bitrev[7]].Im; + + tmp5 = SQRT1_2 * (tmp1 + tmp3); + tmp1 = SQRT1_2 * (tmp3 - tmp1); + tmp3 = SQRT1_2 * (tmp2 - tmp4); + tmp2 = SQRT1_2 * (tmp2 + tmp4); + + tmp4 = tmp5 + tmp3; + tmp5 = tmp5 - tmp3; + tmp3 = tmp1 + tmp2; + tmp1 = tmp1 - tmp2; + + p_tmp[5].Re = p_tmp[1].Re - tmp4; + p_tmp[1].Re = p_tmp[1].Re + tmp4; + p_tmp[5].Im = p_tmp[1].Im - tmp3; + p_tmp[1].Im = p_tmp[1].Im + tmp3; + p_tmp[7].Re = p_tmp[3].Re - tmp1; + p_tmp[3].Re = p_tmp[3].Re + tmp1; + p_tmp[7].Im = p_tmp[3].Im + tmp5; + p_tmp[3].Im = p_tmp[3].Im - tmp5; + } + + step = 1 << (TWIDDLE_TABLE_ORDER - 4); + n1_4 = 4; /* Quarter of the sub-transform size. */ + /* Outer loop that loops over FFT stages. */ + for (uint32_t fft_stage = 4; fft_stage <= pFFTSpec->order - 1; ++fft_stage) { + OMX_U32 n1_2 = 2 * n1_4; + OMX_U32 n3_4 = 3 * n1_4; + num_transforms = (num_transforms >> 1) | 1; + /* + * Loop performing sub-transforms of size 16 and higher. + * The actual size depends on the stage. + */ + for (uint32_t n = 0; n < num_transforms; ++n) { + OMX_U32 offset = pFFTSpec->pOffset[n] << fft_stage; + OMX_FC32* p_tmp = p_buf + offset; + + tmp1 = p_tmp[n1_2].Re + p_tmp[n3_4].Re; + tmp2 = p_tmp[n1_2].Re - p_tmp[n3_4].Re; + tmp3 = p_tmp[n1_2].Im + p_tmp[n3_4].Im; + tmp4 = p_tmp[n1_2].Im - p_tmp[n3_4].Im; + + p_tmp[n1_2].Re = p_tmp[0].Re - tmp1; + p_tmp[n1_2].Im = p_tmp[0].Im - tmp3; + p_tmp[0].Re = p_tmp[0].Re + tmp1; + p_tmp[0].Im = p_tmp[0].Im + tmp3; + p_tmp[n3_4].Re = p_tmp[n1_4].Re - tmp4; + p_tmp[n3_4].Im = p_tmp[n1_4].Im + tmp2; + p_tmp[n1_4].Re = p_tmp[n1_4].Re + tmp4; + p_tmp[n1_4].Im = p_tmp[n1_4].Im - tmp2; + + /* Twiddle table is initialized for the maximal FFT size. */ + w_re_ptr = pFFTSpec->pTwiddle + step; + w_im_ptr = + pFFTSpec->pTwiddle + (OMX_U32)(1 << TWIDDLE_TABLE_ORDER - 2) - step; + + /* + * Loop performing split-radix butterfly operations for + * one sub-transform. + */ + for (uint32_t i = 1; i < n1_4; ++i) { + w_re = *w_re_ptr; + w_im = *w_im_ptr; + + tmp1 = w_re * p_tmp[n1_2 + i].Re + w_im * p_tmp[n1_2 + i].Im; + tmp2 = w_re * p_tmp[n1_2 + i].Im - w_im * p_tmp[n1_2 + i].Re; + tmp3 = w_re * p_tmp[n3_4 + i].Re - w_im * p_tmp[n3_4 + i].Im; + tmp4 = w_re * p_tmp[n3_4 + i].Im + w_im * p_tmp[n3_4 + i].Re; + + tmp5 = tmp1 + tmp3; + tmp1 = tmp1 - tmp3; + tmp6 = tmp2 + tmp4; + tmp2 = tmp2 - tmp4; + + p_tmp[n1_2 + i].Re = p_tmp[i].Re - tmp5; + p_tmp[n1_2 + i].Im = p_tmp[i].Im - tmp6; + p_tmp[i].Re = p_tmp[i].Re + tmp5; + p_tmp[i].Im = p_tmp[i].Im + tmp6; + p_tmp[n3_4 + i].Re = p_tmp[n1_4 + i].Re - tmp2; + p_tmp[n3_4 + i].Im = p_tmp[n1_4 + i].Im + tmp1; + p_tmp[n1_4 + i].Re = p_tmp[n1_4 + i].Re + tmp2; + p_tmp[n1_4 + i].Im = p_tmp[n1_4 + i].Im - tmp1; + + w_re_ptr += step; + w_im_ptr -= step; + } + } + step >>= 1; + n1_4 <<= 1; + } + + /* Additional computation to get the output for full FFT size. */ + w_re_ptr = pFFTSpec->pTwiddle + step; + w_im_ptr = + pFFTSpec->pTwiddle + (OMX_U32)(1 << TWIDDLE_TABLE_ORDER - 2) - step; + + for (uint32_t i = 1; i < fft_size / 8; ++i) { + tmp1 = p_buf[i].Re; + tmp2 = p_buf[i].Im; + tmp3 = p_buf[fft_size / 2 - i].Re; + tmp4 = p_buf[fft_size / 2 - i].Im; + + tmp5 = tmp1 + tmp3; + tmp6 = tmp1 - tmp3; + tmp7 = tmp2 + tmp4; + tmp8 = tmp2 - tmp4; + + tmp1 = p_buf[i + fft_size / 4].Re; + tmp2 = p_buf[i + fft_size / 4].Im; + tmp3 = p_buf[fft_size / 4 - i].Re; + tmp4 = p_buf[fft_size / 4 - i].Im; + + w_re = *w_re_ptr; + w_im = *w_im_ptr; + + p_dst[i].Re = 0.5f * (tmp5 + w_re * tmp7 - w_im * tmp6); + p_dst[i].Im = 0.5f * (tmp8 - w_re * tmp6 - w_im * tmp7); + p_dst[fft_size / 2 - i].Re = 0.5f * (tmp5 - w_re * tmp7 + w_im * tmp6); + p_dst[fft_size / 2 - i].Im = 0.5f * (-tmp8 - w_re * tmp6 - w_im * tmp7); + + tmp5 = tmp1 + tmp3; + tmp6 = tmp1 - tmp3; + tmp7 = tmp2 + tmp4; + tmp8 = tmp2 - tmp4; + + p_dst[i + fft_size / 4].Re = 0.5f * (tmp5 - w_im * tmp7 - w_re * tmp6); + p_dst[i + fft_size / 4].Im = 0.5f * (tmp8 + w_im * tmp6 - w_re * tmp7); + p_dst[fft_size / 4 - i].Re = 0.5f * (tmp5 + w_im * tmp7 + w_re * tmp6); + p_dst[fft_size / 4 - i].Im = 0.5f * (-tmp8 + w_im * tmp6 - w_re * tmp7); + + w_re_ptr += step; + w_im_ptr -= step; + } + tmp1 = p_buf[fft_size / 8].Re; + tmp2 = p_buf[fft_size / 8].Im; + tmp3 = p_buf[3 * fft_size / 8].Re; + tmp4 = p_buf[3 * fft_size / 8].Im; + + tmp5 = tmp1 + tmp3; + tmp6 = tmp1 - tmp3; + tmp7 = tmp2 + tmp4; + tmp8 = tmp2 - tmp4; + + w_re = *w_re_ptr; + w_im = *w_im_ptr; + + p_dst[fft_size / 8].Re = 0.5f * (tmp5 + w_re * tmp7 - w_im * tmp6); + p_dst[fft_size / 8].Im = 0.5f * (tmp8 - w_re * tmp6 - w_im * tmp7); + p_dst[3 * fft_size / 8].Re = 0.5f * (tmp5 - w_re * tmp7 + w_im * tmp6); + p_dst[3 * fft_size / 8].Im = 0.5f * (-tmp8 - w_re * tmp6 - w_im * tmp7); + + p_dst[0].Re = p_buf[0].Re + p_buf[0].Im; + p_dst[fft_size / 4].Re = p_buf[fft_size / 4].Re; + p_dst[fft_size / 2].Re = p_buf[0].Re - p_buf[0].Im; + p_dst[0].Im = 0.0f; + p_dst[fft_size / 4].Im = -p_buf[fft_size / 4].Im; + p_dst[fft_size / 2].Im = 0.0f; + + return OMX_Sts_NoErr; +} diff --git a/dl/sp/src/mips/mips_FFTFwd_RToCCS_F32_real.c b/dl/sp/src/mips/mips_FFTFwd_RToCCS_F32_real.c new file mode 100644 index 0000000..9a17567 --- /dev/null +++ b/dl/sp/src/mips/mips_FFTFwd_RToCCS_F32_real.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#include <stdint.h> + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/mipsSP.h" + +OMXResult mips_FFTFwd_RToCCS_F32_real(const OMX_F32* pSrc, + OMX_F32* pDst, + const MIPSFFTSpec_R_FC32* pFFTSpec) { + OMX_U32 num_transforms, step; + OMX_FC32* p_dst = (OMX_FC32*)pDst; + OMX_FC32* p_buf = (OMX_FC32*)pFFTSpec->pBuf; + OMX_F32 tmp1, tmp2, tmp3, tmp4; + OMX_F32* w_re_ptr; + OMX_F32* w_im_ptr; + + /* Transform for order = 2. */ + /* TODO: hard-code the offsets for p_src. */ + if (pFFTSpec->order == 2) { + OMX_U16* p_bitrev = pFFTSpec->pBitRev; + + tmp1 = pSrc[p_bitrev[0]] + pSrc[p_bitrev[1]]; + tmp2 = pSrc[p_bitrev[2]] + pSrc[p_bitrev[3]]; + tmp3 = pSrc[p_bitrev[0]] - pSrc[p_bitrev[1]]; + tmp4 = pSrc[p_bitrev[2]] - pSrc[p_bitrev[3]]; + + p_dst[0].Re = tmp1 + tmp2; + p_dst[2].Re = tmp1 - tmp2; + p_dst[0].Im = 0.0f; + p_dst[2].Im = 0.0f; + p_dst[1].Re = tmp3; + p_dst[1].Im = -tmp4; + + return OMX_Sts_NoErr; + } + + /* + * Loop performing sub-transforms of size 4, which contain two butterfly + * operations. Reading the input signal from split-radix bitreverse offsets. + */ + num_transforms = (SUBTRANSFORM_CONST >> (16 - pFFTSpec->order)) | 1; + for (uint32_t n = 0; n < num_transforms; ++n) { + OMX_U32 offset = pFFTSpec->pOffset[n] << 2; + OMX_FC32* p_tmp = p_buf + offset; + OMX_U16* p_bitrev = pFFTSpec->pBitRev + offset; + + tmp1 = pSrc[p_bitrev[0]] + pSrc[p_bitrev[1]]; + tmp2 = pSrc[p_bitrev[2]] + pSrc[p_bitrev[3]]; + tmp3 = pSrc[p_bitrev[0]] - pSrc[p_bitrev[1]]; + tmp4 = pSrc[p_bitrev[2]] - pSrc[p_bitrev[3]]; + + p_tmp[0].Re = tmp1 + tmp2; + p_tmp[2].Re = tmp1 - tmp2; + p_tmp[0].Im = 0.0f; + p_tmp[2].Im = 0.0f; + p_tmp[1].Re = tmp3; + p_tmp[3].Re = tmp3; + p_tmp[1].Im = -tmp4; + p_tmp[3].Im = tmp4; + } + + /* + * Loop performing sub-transforms of size 8, + * which contain four butterfly operations. + */ + num_transforms >>= 1; + if (!num_transforms) { + /* + * Means the FFT size is equal to 8, so this is the last stage. Place the + * output to the destination buffer and avoid unnecessary computations. + */ + OMX_FC32* p_tmp = p_buf; + OMX_U16* p_bitrev = pFFTSpec->pBitRev; + OMX_F32 tmp5; + + tmp1 = pSrc[p_bitrev[4]] + pSrc[p_bitrev[5]]; + tmp2 = pSrc[p_bitrev[6]] + pSrc[p_bitrev[7]]; + tmp3 = tmp1 + tmp2; + tmp4 = tmp1 - tmp2; + + tmp1 = pSrc[p_bitrev[4]] - pSrc[p_bitrev[5]]; + tmp2 = pSrc[p_bitrev[6]] - pSrc[p_bitrev[7]]; + tmp5 = SQRT1_2 * (tmp1 + tmp2); + tmp1 = SQRT1_2 * (tmp1 - tmp2); + + p_dst[4].Re = p_tmp[0].Re - tmp3; + p_dst[0].Re = p_tmp[0].Re + tmp3; + p_dst[0].Im = p_tmp[0].Im; + p_dst[4].Im = p_tmp[0].Im; + p_dst[2].Re = p_tmp[2].Re; + p_dst[2].Im = p_tmp[2].Im - tmp4; + p_dst[1].Re = p_tmp[1].Re + tmp5; + p_dst[1].Im = p_tmp[1].Im - tmp1; + p_dst[3].Re = p_tmp[3].Re - tmp5; + p_dst[3].Im = p_tmp[3].Im - tmp1; + + return OMX_Sts_NoErr; + } + + num_transforms |= 1; + + for (uint32_t n = 0; n < num_transforms; ++n) { + OMX_U32 offset = pFFTSpec->pOffset[n] << 3; + OMX_FC32* p_tmp = p_buf + offset; + OMX_U16* p_bitrev = pFFTSpec->pBitRev + offset; + OMX_F32 tmp5; + + tmp1 = pSrc[p_bitrev[4]] + pSrc[p_bitrev[5]]; + tmp2 = pSrc[p_bitrev[6]] + pSrc[p_bitrev[7]]; + tmp3 = tmp1 + tmp2; + tmp4 = tmp1 - tmp2; + + tmp1 = pSrc[p_bitrev[4]] - pSrc[p_bitrev[5]]; + tmp2 = pSrc[p_bitrev[6]] - pSrc[p_bitrev[7]]; + tmp5 = SQRT1_2 * (tmp1 + tmp2); + tmp1 = SQRT1_2 * (tmp1 - tmp2); + + p_tmp[4].Re = p_tmp[0].Re - tmp3; + p_tmp[0].Re = p_tmp[0].Re + tmp3; + p_tmp[4].Im = p_tmp[0].Im; + p_tmp[6].Re = p_tmp[2].Re; + p_tmp[6].Im = p_tmp[2].Im + tmp4; + p_tmp[2].Im = p_tmp[2].Im - tmp4; + + p_tmp[5].Re = p_tmp[1].Re - tmp5; + p_tmp[1].Re = p_tmp[1].Re + tmp5; + p_tmp[5].Im = p_tmp[1].Im + tmp1; + p_tmp[1].Im = p_tmp[1].Im - tmp1; + p_tmp[7].Re = p_tmp[3].Re + tmp5; + p_tmp[3].Re = p_tmp[3].Re - tmp5; + p_tmp[7].Im = p_tmp[3].Im + tmp1; + p_tmp[3].Im = p_tmp[3].Im - tmp1; + } + + step = 1 << (TWIDDLE_TABLE_ORDER - 4); + /* + * Last FFT stage, performing sub-transforms of size 16. Place the output + * into the destination buffer and avoid unnecessary computations. + */ + tmp1 = p_buf[8].Re + p_buf[12].Re; + tmp2 = p_buf[8].Re - p_buf[12].Re; + tmp3 = p_buf[8].Im + p_buf[12].Im; + tmp4 = p_buf[8].Im - p_buf[12].Im; + + p_dst[8].Re = p_buf[0].Re - tmp1; + p_dst[0].Re = p_buf[0].Re + tmp1; + p_dst[8].Im = p_buf[0].Im - tmp3; + p_dst[0].Im = p_buf[0].Im + tmp3; + p_dst[4].Re = p_buf[4].Re + tmp4; + p_dst[4].Im = p_buf[4].Im - tmp2; + + w_re_ptr = pFFTSpec->pTwiddle + step; + w_im_ptr = + pFFTSpec->pTwiddle + (OMX_U32)(1 << TWIDDLE_TABLE_ORDER - 2) - step; + + /* Loop performing split-radix butterfly operations. */ + for (uint32_t n = 1; n < 4; ++n) { + OMX_F32 tmp5, tmp6; + OMX_F32 w_re = *w_re_ptr; + OMX_F32 w_im = *w_im_ptr; + + tmp1 = w_re * p_buf[8 + n].Re + w_im * p_buf[8 + n].Im; + tmp2 = w_re * p_buf[8 + n].Im - w_im * p_buf[8 + n].Re; + tmp3 = w_re * p_buf[12 + n].Re - w_im * p_buf[12 + n].Im; + tmp4 = w_re * p_buf[12 + n].Im + w_im * p_buf[12 + n].Re; + + tmp5 = tmp1 + tmp3; + tmp1 = tmp1 - tmp3; + tmp6 = tmp2 + tmp4; + tmp2 = tmp2 - tmp4; + + p_dst[n].Re = p_buf[n].Re + tmp5; + p_dst[n].Im = p_buf[n].Im + tmp6; + p_dst[4 + n].Re = p_buf[4 + n].Re + tmp2; + p_dst[4 + n].Im = p_buf[4 + n].Im - tmp1; + + w_re_ptr += step; + w_im_ptr -= step; + } + return OMX_Sts_NoErr; +} diff --git a/dl/sp/src/mips/mips_FFTInv_CCSToR_F32_complex.c b/dl/sp/src/mips/mips_FFTInv_CCSToR_F32_complex.c new file mode 100644 index 0000000..88f93cc --- /dev/null +++ b/dl/sp/src/mips/mips_FFTInv_CCSToR_F32_complex.c @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#include <stdint.h> + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/mipsSP.h" + +OMXResult mips_FFTInv_CCSToR_F32_complex(const OMX_F32* pSrc, + OMX_F32* pDst, + const MIPSFFTSpec_R_FC32* pFFTSpec) { + OMX_U32 num_transforms, step; + /* Quarter, half and three-quarters of transform size. */ + OMX_U32 n1_4, n1_2, n3_4; + OMX_F32* w_re_ptr; + OMX_F32* w_im_ptr; + OMX_U32 fft_size = 1 << pFFTSpec->order; + OMX_FC32* p_buf = (OMX_FC32*)pFFTSpec->pBuf; + const OMX_FC32* p_src = (const OMX_FC32*)pSrc; + OMX_FC32* p_dst; + OMX_U16* p_bitrev = pFFTSpec->pBitRevInv; + OMX_F32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, factor; + OMX_F32 w_re, w_im; + + step = 1 << (TWIDDLE_TABLE_ORDER - pFFTSpec->order); + w_re_ptr = pFFTSpec->pTwiddle + step; + w_im_ptr = + pFFTSpec->pTwiddle + (OMX_U32)(1 << (TWIDDLE_TABLE_ORDER - 2)) - step; + + /* + * Preliminary loop performing input adaptation due to computing real FFT + * through complex FFT of half the size. + */ + for (uint32_t n = 1; n < fft_size / 8; ++n) { + tmp1 = p_src[n].Re; + tmp2 = p_src[n].Im; + tmp3 = p_src[fft_size / 2 - n].Re; + tmp4 = p_src[fft_size / 2 - n].Im; + + tmp5 = tmp1 + tmp3; + tmp6 = tmp1 - tmp3; + tmp7 = tmp2 + tmp4; + tmp8 = tmp2 - tmp4; + + w_re = *w_re_ptr; + w_im = *w_im_ptr; + + p_buf[p_bitrev[n]].Re = 0.5f * (tmp5 - w_re * tmp7 - w_im * tmp6); + p_buf[p_bitrev[n]].Im = 0.5f * (tmp8 + w_re * tmp6 - w_im * tmp7); + p_buf[p_bitrev[fft_size / 2 - n]].Re = + 0.5f * (tmp5 + w_re * tmp7 + w_im * tmp6); + p_buf[p_bitrev[fft_size / 2 - n]].Im = + 0.5f * (-tmp8 + w_re * tmp6 - w_im * tmp7); + + tmp1 = p_src[n + fft_size / 4].Re; + tmp2 = p_src[n + fft_size / 4].Im; + tmp3 = p_src[fft_size / 4 - n].Re; + tmp4 = p_src[fft_size / 4 - n].Im; + + tmp5 = tmp1 + tmp3; + tmp6 = tmp1 - tmp3; + tmp7 = tmp2 + tmp4; + tmp8 = tmp2 - tmp4; + + p_buf[p_bitrev[n + fft_size / 4]].Re = + 0.5f * (tmp5 + w_im * tmp7 - w_re * tmp6); + p_buf[p_bitrev[n + fft_size / 4]].Im = + 0.5f * (tmp8 - w_im * tmp6 - w_re * tmp7); + p_buf[p_bitrev[fft_size / 4 - n]].Re = + 0.5f * (tmp5 - w_im * tmp7 + w_re * tmp6); + p_buf[p_bitrev[fft_size / 4 - n]].Im = + 0.5f * (-tmp8 - w_im * tmp6 - w_re * tmp7); + + w_re_ptr += step; + w_im_ptr -= step; + } + tmp1 = p_src[fft_size / 8].Re; + tmp2 = p_src[fft_size / 8].Im; + tmp3 = p_src[3 * fft_size / 8].Re; + tmp4 = p_src[3 * fft_size / 8].Im; + + tmp5 = tmp1 + tmp3; + tmp6 = tmp1 - tmp3; + tmp7 = tmp2 + tmp4; + tmp8 = tmp2 - tmp4; + + w_re = *w_re_ptr; + w_im = *w_im_ptr; + + p_buf[p_bitrev[fft_size / 8]].Re = 0.5f * (tmp5 - w_re * tmp7 - w_im * tmp6); + p_buf[p_bitrev[fft_size / 8]].Im = 0.5f * (tmp8 + w_re * tmp6 - w_im * tmp7); + p_buf[p_bitrev[3 * fft_size / 8]].Re = + 0.5f * (tmp5 + w_re * tmp7 + w_im * tmp6); + p_buf[p_bitrev[3 * fft_size / 8]].Im = + 0.5f * (-tmp8 + w_re * tmp6 - w_im * tmp7); + + p_buf[p_bitrev[0]].Re = 0.5f * (p_src[0].Re + p_src[fft_size / 2].Re); + p_buf[p_bitrev[0]].Im = 0.5f * (p_src[0].Re - p_src[fft_size / 2].Re); + p_buf[p_bitrev[fft_size / 4]].Re = p_src[fft_size / 4].Re; + p_buf[p_bitrev[fft_size / 4]].Im = -p_src[fft_size / 4].Im; + + /* + * Loop performing sub-transforms of size 4, + * which contain 2 butterfly operations. + */ + num_transforms = (SUBTRANSFORM_CONST >> (17 - pFFTSpec->order)) | 1; + for (uint32_t n = 0; n < num_transforms; ++n) { + OMX_U32 offset = pFFTSpec->pOffset[n] << 2; + OMX_FC32* p_tmp = p_buf + offset; + + tmp1 = p_tmp[0].Re + p_tmp[1].Re; + tmp2 = p_tmp[0].Im + p_tmp[1].Im; + tmp3 = p_tmp[0].Re - p_tmp[1].Re; + tmp4 = p_tmp[0].Im - p_tmp[1].Im; + tmp5 = p_tmp[2].Re + p_tmp[3].Re; + tmp6 = p_tmp[2].Im + p_tmp[3].Im; + tmp8 = p_tmp[2].Im - p_tmp[3].Im; + tmp7 = p_tmp[2].Re - p_tmp[3].Re; + + p_tmp[0].Re = tmp1 + tmp5; + p_tmp[2].Re = tmp1 - tmp5; + p_tmp[0].Im = tmp2 + tmp6; + p_tmp[2].Im = tmp2 - tmp6; + p_tmp[1].Re = tmp3 - tmp8; + p_tmp[3].Re = tmp3 + tmp8; + p_tmp[1].Im = tmp4 + tmp7; + p_tmp[3].Im = tmp4 - tmp7; + } + + num_transforms = (num_transforms >> 1) | 1; + /* + * Loop performing sub-transforms of size 8, + * which contain four butterfly operations. + */ + for (uint32_t n = 0; n < num_transforms; ++n) { + OMX_U32 offset = pFFTSpec->pOffset[n] << 3; + OMX_FC32* p_tmp = p_buf + offset; + + tmp1 = p_tmp[4].Re + p_tmp[5].Re; + tmp3 = p_tmp[6].Re + p_tmp[7].Re; + tmp2 = p_tmp[4].Im + p_tmp[5].Im; + tmp4 = p_tmp[6].Im + p_tmp[7].Im; + + tmp5 = tmp1 + tmp3; + tmp7 = tmp1 - tmp3; + tmp6 = tmp2 + tmp4; + tmp8 = tmp2 - tmp4; + + tmp1 = p_tmp[4].Re - p_tmp[5].Re; + tmp2 = p_tmp[4].Im - p_tmp[5].Im; + tmp3 = p_tmp[6].Re - p_tmp[7].Re; + tmp4 = p_tmp[6].Im - p_tmp[7].Im; + + p_tmp[4].Re = p_tmp[0].Re - tmp5; + p_tmp[0].Re = p_tmp[0].Re + tmp5; + p_tmp[4].Im = p_tmp[0].Im - tmp6; + p_tmp[0].Im = p_tmp[0].Im + tmp6; + p_tmp[6].Re = p_tmp[2].Re + tmp8; + p_tmp[2].Re = p_tmp[2].Re - tmp8; + p_tmp[6].Im = p_tmp[2].Im - tmp7; + p_tmp[2].Im = p_tmp[2].Im + tmp7; + + tmp5 = SQRT1_2 * (tmp1 - tmp2); + tmp7 = SQRT1_2 * (tmp3 + tmp4); + tmp6 = SQRT1_2 * (tmp1 + tmp2); + tmp8 = SQRT1_2 * (tmp4 - tmp3); + + tmp1 = tmp5 + tmp7; + tmp3 = tmp5 - tmp7; + tmp2 = tmp6 + tmp8; + tmp4 = tmp6 - tmp8; + + p_tmp[5].Re = p_tmp[1].Re - tmp1; + p_tmp[1].Re = p_tmp[1].Re + tmp1; + p_tmp[5].Im = p_tmp[1].Im - tmp2; + p_tmp[1].Im = p_tmp[1].Im + tmp2; + p_tmp[7].Re = p_tmp[3].Re + tmp4; + p_tmp[3].Re = p_tmp[3].Re - tmp4; + p_tmp[7].Im = p_tmp[3].Im - tmp3; + p_tmp[3].Im = p_tmp[3].Im + tmp3; + } + + step = 1 << (TWIDDLE_TABLE_ORDER - 4); + n1_4 = 4; + /* Outer loop that loops over FFT stages. */ + for (uint32_t fft_stage = 4; fft_stage <= pFFTSpec->order - 2; ++fft_stage) { + n1_2 = 2 * n1_4; + n3_4 = 3 * n1_4; + num_transforms = (num_transforms >> 1) | 1; + for (uint32_t n = 0; n < num_transforms; ++n) { + OMX_U32 offset = pFFTSpec->pOffset[n] << fft_stage; + OMX_FC32* p_tmp = p_buf + offset; + + tmp1 = p_tmp[n1_2].Re + p_tmp[n3_4].Re; + tmp2 = p_tmp[n1_2].Re - p_tmp[n3_4].Re; + tmp3 = p_tmp[n1_2].Im + p_tmp[n3_4].Im; + tmp4 = p_tmp[n1_2].Im - p_tmp[n3_4].Im; + + p_tmp[n1_2].Re = p_tmp[0].Re - tmp1; + p_tmp[0].Re = p_tmp[0].Re + tmp1; + p_tmp[n1_2].Im = p_tmp[0].Im - tmp3; + p_tmp[0].Im = p_tmp[0].Im + tmp3; + p_tmp[n3_4].Re = p_tmp[n1_4].Re + tmp4; + p_tmp[n1_4].Re = p_tmp[n1_4].Re - tmp4; + p_tmp[n3_4].Im = p_tmp[n1_4].Im - tmp2; + p_tmp[n1_4].Im = p_tmp[n1_4].Im + tmp2; + + w_re_ptr = pFFTSpec->pTwiddle + step; + w_im_ptr = + pFFTSpec->pTwiddle + (OMX_U32)(1 << TWIDDLE_TABLE_ORDER - 2) - step; + + /* + * Loop performing split-radix butterfly operations for one sub-transform. + */ + for (uint32_t i = 1; i < n1_4; ++i) { + w_re = *w_re_ptr; + w_im = *w_im_ptr; + + tmp1 = w_re * p_tmp[n1_2 + i].Re - w_im * p_tmp[n1_2 + i].Im; + tmp2 = w_re * p_tmp[n1_2 + i].Im + w_im * p_tmp[n1_2 + i].Re; + tmp3 = w_re * p_tmp[n3_4 + i].Re + w_im * p_tmp[n3_4 + i].Im; + tmp4 = w_re * p_tmp[n3_4 + i].Im - w_im * p_tmp[n3_4 + i].Re; + + tmp5 = tmp1 + tmp3; + tmp1 = tmp1 - tmp3; + tmp6 = tmp2 + tmp4; + tmp2 = tmp2 - tmp4; + + p_tmp[n1_2 + i].Re = p_tmp[i].Re - tmp5; + p_tmp[i].Re = p_tmp[i].Re + tmp5; + p_tmp[n1_2 + i].Im = p_tmp[i].Im - tmp6; + p_tmp[i].Im = p_tmp[i].Im + tmp6; + p_tmp[n3_4 + i].Re = p_tmp[n1_4 + i].Re + tmp2; + p_tmp[n1_4 + i].Re = p_tmp[n1_4 + i].Re - tmp2; + p_tmp[n3_4 + i].Im = p_tmp[n1_4 + i].Im - tmp1; + p_tmp[n1_4 + i].Im = p_tmp[n1_4 + i].Im + tmp1; + + w_re_ptr += step; + w_im_ptr -= step; + } + } + step >>= 1; + n1_4 <<= 1; + } + + /* Last FFT stage, write data to output buffer. */ + n1_2 = 2 * n1_4; + n3_4 = 3 * n1_4; + factor = (OMX_F32)2.0f / fft_size; + + p_dst = (OMX_FC32*)pDst; + + tmp1 = p_buf[n1_2].Re + p_buf[n3_4].Re; + tmp2 = p_buf[n1_2].Re - p_buf[n3_4].Re; + tmp3 = p_buf[n1_2].Im + p_buf[n3_4].Im; + tmp4 = p_buf[n1_2].Im - p_buf[n3_4].Im; + + p_dst[n1_2].Re = factor * (p_buf[0].Re - tmp1); + p_dst[0].Re = factor * (p_buf[0].Re + tmp1); + p_dst[n1_2].Im = factor * (p_buf[0].Im - tmp3); + p_dst[0].Im = factor * (p_buf[0].Im + tmp3); + p_dst[n3_4].Re = factor * (p_buf[n1_4].Re + tmp4); + p_dst[n1_4].Re = factor * (p_buf[n1_4].Re - tmp4); + p_dst[n3_4].Im = factor * (p_buf[n1_4].Im - tmp2); + p_dst[n1_4].Im = factor * (p_buf[n1_4].Im + tmp2); + + w_re_ptr = pFFTSpec->pTwiddle + step; + w_im_ptr = + pFFTSpec->pTwiddle + (OMX_U32)(1 << TWIDDLE_TABLE_ORDER - 2) - step; + + for (uint32_t i = 1; i < n1_4; ++i) { + w_re = *w_re_ptr; + w_im = *w_im_ptr; + + tmp1 = w_re * p_buf[n1_2 + i].Re - w_im * p_buf[n1_2 + i].Im; + tmp2 = w_re * p_buf[n1_2 + i].Im + w_im * p_buf[n1_2 + i].Re; + tmp3 = w_re * p_buf[n3_4 + i].Re + w_im * p_buf[n3_4 + i].Im; + tmp4 = w_re * p_buf[n3_4 + i].Im - w_im * p_buf[n3_4 + i].Re; + + tmp5 = tmp1 + tmp3; + tmp1 = tmp1 - tmp3; + tmp6 = tmp2 + tmp4; + tmp2 = tmp2 - tmp4; + + p_dst[n1_2 + i].Re = factor * (p_buf[i].Re - tmp5); + p_dst[i].Re = factor * (p_buf[i].Re + tmp5); + p_dst[n1_2 + i].Im = factor * (p_buf[i].Im - tmp6); + p_dst[i].Im = factor * (p_buf[i].Im + tmp6); + p_dst[n3_4 + i].Re = factor * (p_buf[n1_4 + i].Re + tmp2); + p_dst[n1_4 + i].Re = factor * (p_buf[n1_4 + i].Re - tmp2); + p_dst[n3_4 + i].Im = factor * (p_buf[n1_4 + i].Im - tmp1); + p_dst[n1_4 + i].Im = factor * (p_buf[n1_4 + i].Im + tmp1); + + w_re_ptr += step; + w_im_ptr -= step; + } + + return OMX_Sts_NoErr; +} diff --git a/dl/sp/src/mips/mips_FFTInv_CCSToR_F32_real.c b/dl/sp/src/mips/mips_FFTInv_CCSToR_F32_real.c new file mode 100644 index 0000000..ff7896e --- /dev/null +++ b/dl/sp/src/mips/mips_FFTInv_CCSToR_F32_real.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#include <stdint.h> + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/mipsSP.h" + +OMXResult mips_FFTInv_CCSToR_F32_real(const OMX_F32* pSrc, + OMX_F32* pDst, + const MIPSFFTSpec_R_FC32* pFFTSpec) { + OMX_U32 step, num_transforms; + OMX_FC32* p_buf = (OMX_FC32*)pFFTSpec->pBuf; + const OMX_FC32* p_src = (const OMX_FC32*)pSrc; + OMX_U32 fft_size = 1 << pFFTSpec->order; + OMX_F32 factor, tmp1, tmp2; + OMX_F32* w_re_ptr; + OMX_F32* w_im_ptr; + + /* Copy the input into the auxiliary buffer. */ + for (uint32_t n = 1; n < fft_size / 2; ++n) { + p_buf[pFFTSpec->pBitRevInv[n]] = p_src[n]; + p_buf[pFFTSpec->pBitRevInv[fft_size - n]].Re = p_src[n].Re; + p_buf[pFFTSpec->pBitRevInv[fft_size - n]].Im = -p_src[n].Im; + } + p_buf[0] = p_src[0]; + p_buf[pFFTSpec->pBitRevInv[fft_size / 2]] = p_src[fft_size / 2]; + + factor = (OMX_F32)1.0f / fft_size; + + /* Special case for order == 2, only one sub-transform of size 4. */ + if (pFFTSpec->order == 2) { + OMX_F32 tmp3, tmp4; + + tmp1 = p_buf[0].Re + p_buf[1].Re; + tmp2 = p_buf[2].Re + p_buf[3].Re; + tmp3 = p_buf[0].Re - p_buf[1].Re; + tmp4 = p_buf[2].Im - p_buf[3].Im; + + pDst[0] = factor * (tmp1 + tmp2); + pDst[2] = factor * (tmp1 - tmp2); + pDst[1] = factor * (tmp3 - tmp4); + pDst[3] = factor * (tmp3 + tmp4); + + return OMX_Sts_NoErr; + } + + /* + * Loop performing sub-transforms of size 4, + * which contain two butterfly operations. + */ + num_transforms = (SUBTRANSFORM_CONST >> (16 - pFFTSpec->order)) | 1; + for (uint32_t n = 0; n < num_transforms; ++n) { + OMX_U32 offset = pFFTSpec->pOffset[n] << 2; + OMX_FC32* p_tmp = p_buf + offset; + OMX_F32 tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; + + tmp1 = p_tmp[0].Re + p_tmp[1].Re; + tmp5 = p_tmp[2].Re + p_tmp[3].Re; + tmp2 = p_tmp[0].Im + p_tmp[1].Im; + tmp6 = p_tmp[2].Im + p_tmp[3].Im; + tmp3 = p_tmp[0].Re - p_tmp[1].Re; + tmp8 = p_tmp[2].Im - p_tmp[3].Im; + tmp4 = p_tmp[0].Im - p_tmp[1].Im; + tmp7 = p_tmp[2].Re - p_tmp[3].Re; + + p_tmp[0].Re = tmp1 + tmp5; + p_tmp[2].Re = tmp1 - tmp5; + p_tmp[0].Im = tmp2 + tmp6; + p_tmp[2].Im = tmp2 - tmp6; + p_tmp[1].Re = tmp3 - tmp8; + p_tmp[3].Re = tmp3 + tmp8; + p_tmp[1].Im = tmp4 + tmp7; + p_tmp[3].Im = tmp4 - tmp7; + } + + num_transforms >>= 1; + if (!num_transforms) { + /* + * Special case for order == 3, only one sub-transform of size 8. + * Omit the unnecessary calculations and place the output + * into the destination buffer. + */ + OMX_F32 tmp3, tmp4, tmp5, tmp6; + + tmp1 = p_buf[4].Re + p_buf[5].Re; + tmp2 = p_buf[6].Re + p_buf[7].Re; + tmp3 = p_buf[4].Im + p_buf[5].Im; + tmp4 = p_buf[6].Im + p_buf[7].Im; + + tmp5 = tmp1 + tmp2; + tmp6 = tmp3 - tmp4; + + tmp1 = p_buf[4].Re - p_buf[5].Re; + tmp2 = p_buf[4].Im - p_buf[5].Im; + tmp3 = p_buf[6].Re - p_buf[7].Re; + tmp4 = p_buf[6].Im - p_buf[7].Im; + + pDst[4] = factor * (p_buf[0].Re - tmp5); + pDst[0] = factor * (p_buf[0].Re + tmp5); + pDst[6] = factor * (p_buf[2].Re + tmp6); + pDst[2] = factor * (p_buf[2].Re - tmp6); + + tmp5 = SQRT1_2 * (tmp1 - tmp2); + tmp6 = SQRT1_2 * (tmp3 + tmp4); + tmp1 = SQRT1_2 * (tmp1 + tmp2); + tmp2 = SQRT1_2 * (tmp4 - tmp3); + + tmp3 = tmp5 + tmp6; + tmp4 = tmp1 - tmp2; + + pDst[5] = factor * (p_buf[1].Re - tmp3); + pDst[1] = factor * (p_buf[1].Re + tmp3); + pDst[7] = factor * (p_buf[3].Re + tmp4); + pDst[3] = factor * (p_buf[3].Re - tmp4); + + return OMX_Sts_NoErr; + } + + num_transforms |= 1; + for (uint32_t n = 0; n < num_transforms; ++n) { + /* + * Loop performing sub-transforms of size 8, + * which contain four butterfly operations. + */ + OMX_U32 offset = pFFTSpec->pOffset[n] << 3; + OMX_FC32* p_tmp = p_buf + offset; + OMX_F32 tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; + + tmp1 = p_tmp[4].Re + p_tmp[5].Re; + tmp3 = p_tmp[6].Re + p_tmp[7].Re; + tmp2 = p_tmp[4].Im + p_tmp[5].Im; + tmp4 = p_tmp[6].Im + p_tmp[7].Im; + + tmp5 = tmp1 + tmp3; + tmp7 = tmp1 - tmp3; + tmp6 = tmp2 + tmp4; + tmp8 = tmp2 - tmp4; + + tmp1 = p_tmp[4].Re - p_tmp[5].Re; + tmp2 = p_tmp[4].Im - p_tmp[5].Im; + tmp3 = p_tmp[6].Re - p_tmp[7].Re; + tmp4 = p_tmp[6].Im - p_tmp[7].Im; + + p_tmp[4].Re = p_tmp[0].Re - tmp5; + p_tmp[0].Re = p_tmp[0].Re + tmp5; + p_tmp[4].Im = p_tmp[0].Im - tmp6; + p_tmp[0].Im = p_tmp[0].Im + tmp6; + p_tmp[6].Re = p_tmp[2].Re + tmp8; + p_tmp[2].Re = p_tmp[2].Re - tmp8; + p_tmp[6].Im = p_tmp[2].Im - tmp7; + p_tmp[2].Im = p_tmp[2].Im + tmp7; + + tmp5 = SQRT1_2 * (tmp1 - tmp2); + tmp7 = SQRT1_2 * (tmp3 + tmp4); + tmp6 = SQRT1_2 * (tmp1 + tmp2); + tmp8 = SQRT1_2 * (tmp4 - tmp3); + + tmp1 = tmp5 + tmp7; + tmp3 = tmp5 - tmp7; + tmp2 = tmp6 + tmp8; + tmp4 = tmp6 - tmp8; + + p_tmp[5].Re = p_tmp[1].Re - tmp1; + p_tmp[1].Re = p_tmp[1].Re + tmp1; + p_tmp[5].Im = p_tmp[1].Im - tmp2; + p_tmp[1].Im = p_tmp[1].Im + tmp2; + p_tmp[7].Re = p_tmp[3].Re + tmp4; + p_tmp[3].Re = p_tmp[3].Re - tmp4; + p_tmp[7].Im = p_tmp[3].Im - tmp3; + p_tmp[3].Im = p_tmp[3].Im + tmp3; + } + + step = 1 << (TWIDDLE_TABLE_ORDER - 4); + /* + * Last FFT stage, doing sub-transform of size 16. Avoid unnecessary + * calculations and place the output directly into the destination buffer. + */ + tmp1 = p_buf[8].Re + p_buf[12].Re; + tmp2 = p_buf[8].Im - p_buf[12].Im; + + pDst[8] = factor * (p_buf[0].Re - tmp1); + pDst[0] = factor * (p_buf[0].Re + tmp1); + pDst[12] = factor * (p_buf[4].Re + tmp2); + pDst[4] = factor * (p_buf[4].Re - tmp2); + + w_re_ptr = pFFTSpec->pTwiddle + step; + w_im_ptr = + pFFTSpec->pTwiddle + (OMX_U32)(1 << TWIDDLE_TABLE_ORDER - 2) - step; + + /* Loop performing split-radix butterfly operations. */ + for (uint32_t n = 1; n < 4; ++n) { + OMX_F32 tmp3, tmp4, tmp5; + OMX_F32 w_re = *w_re_ptr; + OMX_F32 w_im = *w_im_ptr; + + tmp1 = w_re * p_buf[8 + n].Re - w_im * p_buf[8 + n].Im; + tmp2 = w_re * p_buf[8 + n].Im + w_im * p_buf[8 + n].Re; + tmp3 = w_re * p_buf[12 + n].Re + w_im * p_buf[12 + n].Im; + tmp4 = w_re * p_buf[12 + n].Im - w_im * p_buf[12 + n].Re; + + tmp5 = tmp1 + tmp3; + tmp2 = tmp2 - tmp4; + + pDst[8 + n] = factor * (p_buf[n].Re - tmp5); + pDst[n] = factor * (p_buf[n].Re + tmp5); + pDst[12 + n] = factor * (p_buf[4 + n].Re + tmp2); + pDst[4 + n] = factor * (p_buf[4 + n].Re - tmp2); + + w_re_ptr += step; + w_im_ptr -= step; + } + return OMX_Sts_NoErr; +} diff --git a/dl/sp/src/mips/omxSP_FFTFwd_RToCCS_F32_Sfs.c b/dl/sp/src/mips/omxSP_FFTFwd_RToCCS_F32_Sfs.c new file mode 100644 index 0000000..c01b970 --- /dev/null +++ b/dl/sp/src/mips/omxSP_FFTFwd_RToCCS_F32_Sfs.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#include <stdint.h> + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/omxSP.h" +#include "dl/sp/api/mipsSP.h" + +extern OMXResult mips_FFTFwd_RToCCS_F32_complex( + const OMX_F32* pSrc, + OMX_F32* pDst, + const MIPSFFTSpec_R_FC32* pFFTSpec); + +extern OMXResult mips_FFTFwd_RToCCS_F32_real( + const OMX_F32* pSrc, + OMX_F32* pDst, + const MIPSFFTSpec_R_FC32* pFFTSpec); + +OMXResult omxSP_FFTFwd_RToCCS_F32_Sfs(const OMX_F32* pSrc, + OMX_F32* pDst, + const OMXFFTSpec_R_F32* pFFTSpec) { + const MIPSFFTSpec_R_FC32* pFFTStruct = (const MIPSFFTSpec_R_FC32*)pFFTSpec; + + /* Buffers must be 32 bytes aligned. */ + if (!pSrc || !pDst || ((uintptr_t)pSrc & 31) || ((uintptr_t)pDst & 31) || + !pFFTSpec) + return OMX_Sts_BadArgErr; + + /* Check if the structure is initialized correctly. */ + if (!pFFTStruct->pBitRev || !pFFTStruct->pBitRevInv || !pFFTStruct->pOffset || + !pFFTStruct->pTwiddle || !pFFTStruct->pBuf || (pFFTStruct->order < 1) || + (pFFTStruct->order > TWIDDLE_TABLE_ORDER)) + return OMX_Sts_BadArgErr; + + /* For order larger than 4, compute Real FFT as Complex FFT of (order - 1). */ + if (pFFTStruct->order > 4) + return mips_FFTFwd_RToCCS_F32_complex(pSrc, pDst, pFFTStruct); + + /* Special case for order == 1. */ + if (pFFTStruct->order == 1) { + pDst[0] = (pSrc[0] + pSrc[1]); + pDst[1] = 0.0f; + pDst[2] = (pSrc[0] - pSrc[1]); + pDst[3] = 0.0f; + return OMX_Sts_NoErr; + } + + /* Other short FFTs. */ + return mips_FFTFwd_RToCCS_F32_real(pSrc, pDst, pFFTStruct); +} diff --git a/dl/sp/src/mips/omxSP_FFTGetBufSize_R_F32.c b/dl/sp/src/mips/omxSP_FFTGetBufSize_R_F32.c new file mode 100644 index 0000000..db575d1 --- /dev/null +++ b/dl/sp/src/mips/omxSP_FFTGetBufSize_R_F32.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/mipsSP.h" +#include "dl/sp/api/omxSP.h" + +OMXResult omxSP_FFTGetBufSize_R_F32(OMX_INT order, OMX_INT* pSize) { + OMX_INT fft_size; + + if (!pSize || (order < 1) || (order > TWIDDLE_TABLE_ORDER)) + return OMX_Sts_BadArgErr; + + /* For order larger than 4, compute Real FFT as Complex FFT of (order - 1). */ + if (order > 4) + fft_size = 1 << (order - 1); + else + fft_size = 1 << order; + + *pSize = sizeof(MIPSFFTSpec_R_FC32) + + /* BitRev Table. */ + sizeof(OMX_U16) * fft_size + + /* BitRevInv Table. */ + sizeof(OMX_U16) * fft_size + + /* Offsets table. */ + sizeof(OMX_U16) * + ((SUBTRANSFORM_CONST >> (16 - TWIDDLE_TABLE_ORDER)) | 1) + + /* pBuf. */ + sizeof(OMX_F32) * (fft_size << 1) + + /* + * Extra bytes to get 32 byte alignment of + * pBitRev, pBitRevInv, pOffset and pBuf. + */ + 124; + + return OMX_Sts_NoErr; +} diff --git a/dl/sp/src/mips/omxSP_FFTInit_R_F32.c b/dl/sp/src/mips/omxSP_FFTInit_R_F32.c new file mode 100644 index 0000000..15749e0 --- /dev/null +++ b/dl/sp/src/mips/omxSP_FFTInit_R_F32.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#include <stdint.h> + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/omxSP.h" +#include "dl/sp/api/mipsSP.h" + +static OMX_U16 SplitRadixPermutation(int i, int size, int inverse) { + int m; + if (size <= 2) + return (i & 1); + m = size >> 1; + if (!(i & m)) + return SplitRadixPermutation(i, m, inverse) * 2; + m >>= 1; + if (inverse == !(i & m)) + return SplitRadixPermutation(i, m, inverse) * 4 + 1; + + return SplitRadixPermutation(i, m, inverse) * 4 - 1; +} + +static void InitFFTOffsetsLUT(OMX_U16* offset_table, + int offset, + int size, + OMX_U32* index) { + if (size < 16) { + offset_table[*index] = (OMX_U16)(offset >> 2); + (*index)++; + } else { + InitFFTOffsetsLUT(offset_table, offset, size >> 1, index); + InitFFTOffsetsLUT(offset_table, offset + (size >> 1), size >> 2, index); + InitFFTOffsetsLUT(offset_table, offset + 3 * (size >> 2), size >> 2, index); + } +} + +OMXResult omxSP_FFTInit_R_F32(OMXFFTSpec_R_F32* pFFTSpec, OMX_INT order) { + OMX_U32 n; + uint32_t fft_size; + OMX_U16* p_bit_rev; + OMX_U16* p_bit_rev_inv; + OMX_U16* p_offset; + OMX_F32* p_twiddle; + OMX_F32* p_buf; + OMX_U32 tmp; + MIPSFFTSpec_R_FC32* pFFTStruct = (MIPSFFTSpec_R_FC32*)pFFTSpec; + + if (!pFFTSpec || (order < 1) || (order > TWIDDLE_TABLE_ORDER)) + return OMX_Sts_BadArgErr; + + /* For order larger than 4, compute Real FFT as Complex FFT of (order - 1). */ + if (order > 4) + fft_size = 1 << (order - 1); + else + fft_size = 1 << order; + + p_twiddle = mipsSP_FFT_F32TwiddleTable; + + p_bit_rev = (OMX_U16*)((OMX_S8*)pFFTSpec + sizeof(MIPSFFTSpec_R_FC32)); + /* Align to 32 byte boundary. */ + tmp = ((uintptr_t)p_bit_rev) & 31; + if (tmp) + p_bit_rev = (OMX_U16*)((OMX_S8*)p_bit_rev + (32 - tmp)); + + p_bit_rev_inv = (OMX_U16*)((OMX_S8*)p_bit_rev + fft_size * sizeof(OMX_U16)); + /* Align to 32 byte boundary. */ + tmp = ((uintptr_t)p_bit_rev_inv) & 31; + if (tmp) + p_bit_rev_inv = (OMX_U16*)((OMX_S8*)p_bit_rev_inv + (32 - tmp)); + + p_offset = (OMX_U16*)((OMX_S8*)p_bit_rev_inv + fft_size * sizeof(OMX_U16)); + /* Align to 32 byte boundary. */ + tmp = ((uintptr_t)p_offset) & 31; + if (tmp) + p_offset = (OMX_U16*)((OMX_S8*)p_offset + (32 - tmp)); + + p_buf = (OMX_F32*)((OMX_S8*)p_offset + + ((SUBTRANSFORM_CONST >> (16 - TWIDDLE_TABLE_ORDER)) | 1) * + sizeof(OMX_U16)); + + /* Align to 32 byte boundary. */ + tmp = ((uintptr_t)p_buf) & 31; + if (tmp) + p_buf = (OMX_F32*)((OMX_S8*)p_buf + (32 - tmp)); + + /* Calculate BitRevInv indexes. */ + for (uint32_t i = 0; i < fft_size; ++i) + p_bit_rev_inv[-SplitRadixPermutation(i, fft_size, 0) & (fft_size - 1)] = i; + + /* Calculate BitRev indexes. */ + for (uint32_t i = 0; i < fft_size; ++i) + p_bit_rev[p_bit_rev_inv[i]] = i; + + /* Calculate Offsets. */ + n = 0; + InitFFTOffsetsLUT(p_offset, 0, 1 << TWIDDLE_TABLE_ORDER, &n); + + /* + * Double-check if the offset tables are initialized correctly. + * Note: the bit-reverse tables and the initialization algorithm for + * pFFTStruct->pOffset table are thoroughly tested, so this check is + * probabaly redundant. However, keeping this just to make sure the offsets + * will not exceed the buffer boundaries. + */ + if (order == 2) { + /* Only check the offsets for the p_bit_rev_inv table. */ + for (uint32_t i = 0; i < fft_size; ++i) { + if (p_bit_rev_inv[i] >= fft_size) + return OMX_Sts_BadArgErr; + } + } else if (order < 5) { + /* Check for p_offset table. */ + int shift = 2; + int over = 4; + int num_transforms = (SUBTRANSFORM_CONST >> (16 - order)) | 1; + for (uint32_t i = 2; i < order; ++i) { + for (uint32_t j = 0; j < num_transforms; ++j) { + if (((p_offset[j] << shift) + over - 1) >= fft_size) + return OMX_Sts_BadArgErr; + } + shift++; + over <<= 1; + num_transforms = (num_transforms >> 1) | 1; + } + /* Check for bit-reverse tables. */ + for (uint32_t i = 0; i < fft_size; ++i) { + if ((p_bit_rev[i] >= fft_size) || (p_bit_rev_inv[i] >= fft_size)) + return OMX_Sts_BadArgErr; + } + } else { + /* Check for p_offset table. */ + int shift = 2; + int over = 4; + int num_transforms = (SUBTRANSFORM_CONST >> (17 - order)) | 1; + for (uint32_t i = 2; i < order; ++i) { + for (uint32_t j = 0; j < num_transforms; ++j) { + if (((p_offset[j] << shift) + over - 1) >= fft_size) + return OMX_Sts_BadArgErr; + } + shift++; + over <<= 1; + num_transforms = (num_transforms >> 1) | 1; + } + /* Check for bit-reverse tables. */ + for (uint32_t i = 0; i < fft_size; ++i) { + if ((p_bit_rev[i] >= fft_size) || (p_bit_rev_inv[i] >= fft_size)) + return OMX_Sts_BadArgErr; + } + } + + pFFTStruct->order = order; + pFFTStruct->pBitRev = p_bit_rev; + pFFTStruct->pBitRevInv = p_bit_rev_inv; + pFFTStruct->pOffset = (const OMX_U16*)p_offset; + pFFTStruct->pTwiddle = p_twiddle; + pFFTStruct->pBuf = p_buf; + + return OMX_Sts_NoErr; +} diff --git a/dl/sp/src/mips/omxSP_FFTInv_CCSToR_F32_Sfs.c b/dl/sp/src/mips/omxSP_FFTInv_CCSToR_F32_Sfs.c new file mode 100644 index 0000000..2bc3482 --- /dev/null +++ b/dl/sp/src/mips/omxSP_FFTInv_CCSToR_F32_Sfs.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#include <stdint.h> + +#include "dl/api/omxtypes.h" +#include "dl/sp/api/omxSP.h" +#include "dl/sp/api/mipsSP.h" + +extern OMXResult mips_FFTInv_CCSToR_F32_complex( + const OMX_F32* pSrc, + OMX_F32* pDst, + const MIPSFFTSpec_R_FC32* pFFTSpec); + +extern OMXResult mips_FFTInv_CCSToR_F32_real( + const OMX_F32* pSrc, + OMX_F32* pDst, + const MIPSFFTSpec_R_FC32* pFFTSpec); + +OMXResult omxSP_FFTInv_CCSToR_F32_Sfs(const OMX_F32* pSrc, + OMX_F32* pDst, + const OMXFFTSpec_R_F32* pFFTSpec) { + const MIPSFFTSpec_R_FC32* pFFTStruct = (const MIPSFFTSpec_R_FC32*)pFFTSpec; + + /* Input buffers must be 32 bytes aligned. */ + if (!pSrc || !pDst || (uintptr_t)pSrc & 31 || (uintptr_t)pDst & 31 || + !pFFTSpec) + return OMX_Sts_BadArgErr; + + /* Check if the structure is initialized correctly. */ + if (!pFFTStruct->pBitRev || !pFFTStruct->pBitRevInv || !pFFTStruct->pOffset || + !pFFTStruct->pTwiddle || !pFFTStruct->pBuf || (pFFTStruct->order < 1) || + (pFFTStruct->order > TWIDDLE_TABLE_ORDER)) + return OMX_Sts_BadArgErr; + + /* + * For order larger than 4, compute Real IFFT as + * Complex IFFT of (order - 1). + */ + if (pFFTStruct->order > 4) + return mips_FFTInv_CCSToR_F32_complex(pSrc, pDst, pFFTStruct); + + /* Special case for order == 1. */ + if (pFFTStruct->order == 1) { + pDst[0] = (pSrc[0] + pSrc[2]) / 2; + pDst[1] = (pSrc[0] - pSrc[2]) / 2; + return OMX_Sts_NoErr; + } + + /* Other short IFFTs. */ + return mips_FFTInv_CCSToR_F32_real(pSrc, pDst, pFFTStruct); +} diff --git a/dl/sp/src/mips/omxSP_FFT_F32TwiddleTable.c b/dl/sp/src/mips/omxSP_FFT_F32TwiddleTable.c new file mode 100644 index 0000000..b778185 --- /dev/null +++ b/dl/sp/src/mips/omxSP_FFT_F32TwiddleTable.c @@ -0,0 +1,1871 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#include "dl/api/omxtypes.h" + +/* + * Twiddle table for split radix FFT in float format. + * It contains factors cos (W * i) where W = 2*PI/N and 0 <= i < N/4. + * N is the max size of the FFT. Here is N = 2^12 or N = 2^15, depending + * on the TWIDDLE_TABLE_ORDER parameter. + */ + +const OMX_F32 mipsSP_FFT_F32TwiddleTable[1 << (TWIDDLE_TABLE_ORDER - 2)] = { +#if TWIDDLE_TABLE_ORDER == 15 + 1.0000000000f, 1.0000000000f, 0.9999999404f, 0.9999998212f, 0.9999997020f, + 0.9999995232f, 0.9999993443f, 0.9999991059f, 0.9999988079f, 0.9999985099f, + 0.9999981523f, 0.9999977946f, 0.9999973774f, 0.9999969006f, 0.9999964237f, + 0.9999958873f, 0.9999952912f, 0.9999946952f, 0.9999940395f, 0.9999933839f, + 0.9999926686f, 0.9999918938f, 0.9999911189f, 0.9999902844f, 0.9999893904f, + 0.9999884963f, 0.9999876022f, 0.9999865890f, 0.9999855757f, 0.9999845624f, + 0.9999834299f, 0.9999823570f, 0.9999811649f, 0.9999799728f, 0.9999787211f, + 0.9999774694f, 0.9999761581f, 0.9999748468f, 0.9999734759f, 0.9999720454f, + 0.9999706149f, 0.9999691248f, 0.9999675751f, 0.9999660254f, 0.9999644160f, + 0.9999627471f, 0.9999610782f, 0.9999594092f, 0.9999576211f, 0.9999558330f, + 0.9999540448f, 0.9999521971f, 0.9999502897f, 0.9999483824f, 0.9999464154f, + 0.9999443889f, 0.9999423623f, 0.9999402761f, 0.9999381304f, 0.9999359846f, + 0.9999338388f, 0.9999315739f, 0.9999293089f, 0.9999270439f, 0.9999247193f, + 0.9999223351f, 0.9999199510f, 0.9999174476f, 0.9999150038f, 0.9999125004f, + 0.9999099374f, 0.9999073148f, 0.9999046922f, 0.9999020100f, 0.9998993278f, + 0.9998965859f, 0.9998938441f, 0.9998909831f, 0.9998881817f, 0.9998852611f, + 0.9998823404f, 0.9998793602f, 0.9998763800f, 0.9998733401f, 0.9998703003f, + 0.9998672009f, 0.9998640418f, 0.9998608828f, 0.9998576641f, 0.9998543859f, + 0.9998511076f, 0.9998477697f, 0.9998444319f, 0.9998410344f, 0.9998375773f, + 0.9998341203f, 0.9998306036f, 0.9998270273f, 0.9998234510f, 0.9998198152f, + 0.9998161793f, 0.9998124838f, 0.9998087287f, 0.9998049736f, 0.9998011589f, + 0.9997973442f, 0.9997934699f, 0.9997895360f, 0.9997856021f, 0.9997816086f, + 0.9997775555f, 0.9997735023f, 0.9997693896f, 0.9997652769f, 0.9997611046f, + 0.9997568727f, 0.9997526407f, 0.9997483492f, 0.9997440577f, 0.9997397065f, + 0.9997352958f, 0.9997308850f, 0.9997264147f, 0.9997218847f, 0.9997173548f, + 0.9997127652f, 0.9997081757f, 0.9997035265f, 0.9996988177f, 0.9996941090f, + 0.9996893406f, 0.9996845126f, 0.9996796846f, 0.9996748567f, 0.9996699095f, + 0.9996649623f, 0.9996600151f, 0.9996550083f, 0.9996499419f, 0.9996448159f, + 0.9996396899f, 0.9996345639f, 0.9996293187f, 0.9996240735f, 0.9996188283f, + 0.9996135235f, 0.9996081591f, 0.9996027946f, 0.9995973706f, 0.9995918870f, + 0.9995864034f, 0.9995808601f, 0.9995753169f, 0.9995697141f, 0.9995640516f, + 0.9995583892f, 0.9995526671f, 0.9995468855f, 0.9995411038f, 0.9995352626f, + 0.9995294213f, 0.9995235205f, 0.9995175600f, 0.9995115995f, 0.9995055795f, + 0.9994995594f, 0.9994934797f, 0.9994873405f, 0.9994812012f, 0.9994750023f, + 0.9994687438f, 0.9994624853f, 0.9994561672f, 0.9994498491f, 0.9994434714f, + 0.9994370341f, 0.9994305968f, 0.9994240999f, 0.9994176030f, 0.9994110465f, + 0.9994044304f, 0.9993978143f, 0.9993911386f, 0.9993844032f, 0.9993776679f, + 0.9993708730f, 0.9993640780f, 0.9993572235f, 0.9993503094f, 0.9993433952f, + 0.9993364215f, 0.9993294477f, 0.9993224144f, 0.9993153214f, 0.9993081689f, + 0.9993010163f, 0.9992938638f, 0.9992866516f, 0.9992793798f, 0.9992721081f, + 0.9992647767f, 0.9992573857f, 0.9992499948f, 0.9992425442f, 0.9992350340f, + 0.9992275238f, 0.9992199540f, 0.9992123842f, 0.9992047548f, 0.9991970658f, + 0.9991893768f, 0.9991816282f, 0.9991738796f, 0.9991660714f, 0.9991582036f, + 0.9991503358f, 0.9991424084f, 0.9991344810f, 0.9991264939f, 0.9991184473f, + 0.9991103411f, 0.9991022348f, 0.9990941286f, 0.9990859628f, 0.9990777373f, + 0.9990694523f, 0.9990611672f, 0.9990528822f, 0.9990444779f, 0.9990360737f, + 0.9990276694f, 0.9990192056f, 0.9990106821f, 0.9990021586f, 0.9989935756f, + 0.9989849329f, 0.9989762902f, 0.9989675879f, 0.9989588857f, 0.9989501238f, + 0.9989413023f, 0.9989324808f, 0.9989235997f, 0.9989146590f, 0.9989057183f, + 0.9988967180f, 0.9988877177f, 0.9988786578f, 0.9988695383f, 0.9988604188f, + 0.9988512397f, 0.9988420606f, 0.9988328218f, 0.9988235235f, 0.9988142252f, + 0.9988048673f, 0.9987954497f, 0.9987860322f, 0.9987765551f, 0.9987670779f, + 0.9987575412f, 0.9987479448f, 0.9987383485f, 0.9987286925f, 0.9987190366f, + 0.9987093210f, 0.9986995459f, 0.9986897111f, 0.9986799359f, 0.9986700416f, + 0.9986601472f, 0.9986501932f, 0.9986402392f, 0.9986302257f, 0.9986201525f, + 0.9986100793f, 0.9985999465f, 0.9985897541f, 0.9985795617f, 0.9985693693f, + 0.9985590577f, 0.9985487461f, 0.9985384345f, 0.9985280633f, 0.9985176325f, + 0.9985071421f, 0.9984966516f, 0.9984861612f, 0.9984755516f, 0.9984650016f, + 0.9984543324f, 0.9984436631f, 0.9984329343f, 0.9984222054f, 0.9984114170f, + 0.9984005690f, 0.9983897209f, 0.9983788133f, 0.9983679056f, 0.9983569384f, + 0.9983459115f, 0.9983348846f, 0.9983237982f, 0.9983127117f, 0.9983015656f, + 0.9982903600f, 0.9982791543f, 0.9982678890f, 0.9982565641f, 0.9982452393f, + 0.9982338548f, 0.9982224703f, 0.9982110262f, 0.9981995225f, 0.9981880188f, + 0.9981764555f, 0.9981648326f, 0.9981532097f, 0.9981415272f, 0.9981298447f, + 0.9981181026f, 0.9981063604f, 0.9980944991f, 0.9980826974f, 0.9980707765f, + 0.9980588555f, 0.9980468750f, 0.9980348945f, 0.9980228543f, 0.9980108142f, + 0.9979987144f, 0.9979865551f, 0.9979743958f, 0.9979621768f, 0.9979498982f, + 0.9979376197f, 0.9979252815f, 0.9979129434f, 0.9979005456f, 0.9978880882f, + 0.9978756309f, 0.9978631139f, 0.9978505373f, 0.9978379607f, 0.9978253245f, + 0.9978126884f, 0.9977999926f, 0.9977872968f, 0.9977744818f, 0.9977617264f, + 0.9977488518f, 0.9977359772f, 0.9977230430f, 0.9977101088f, 0.9976971149f, + 0.9976841211f, 0.9976710677f, 0.9976579547f, 0.9976448417f, 0.9976316690f, + 0.9976184368f, 0.9976052046f, 0.9975919127f, 0.9975786209f, 0.9975652099f, + 0.9975518584f, 0.9975384474f, 0.9975249767f, 0.9975114465f, 0.9974979162f, + 0.9974843264f, 0.9974707365f, 0.9974570870f, 0.9974433780f, 0.9974296689f, + 0.9974159002f, 0.9974021316f, 0.9973883033f, 0.9973744154f, 0.9973605275f, + 0.9973465800f, 0.9973326325f, 0.9973185658f, 0.9973045588f, 0.9972904325f, + 0.9972763062f, 0.9972621799f, 0.9972479939f, 0.9972337484f, 0.9972194433f, + 0.9972051382f, 0.9971908331f, 0.9971764088f, 0.9971620440f, 0.9971475601f, + 0.9971330762f, 0.9971185327f, 0.9971039891f, 0.9970893860f, 0.9970747232f, + 0.9970600605f, 0.9970453382f, 0.9970306158f, 0.9970158339f, 0.9970009923f, + 0.9969861507f, 0.9969712496f, 0.9969563484f, 0.9969413280f, 0.9969263673f, + 0.9969112873f, 0.9968962073f, 0.9968811274f, 0.9968659878f, 0.9968507886f, + 0.9968355894f, 0.9968202710f, 0.9968050122f, 0.9967896938f, 0.9967743158f, + 0.9967588782f, 0.9967434406f, 0.9967279434f, 0.9967124462f, 0.9966968894f, + 0.9966813326f, 0.9966656566f, 0.9966500401f, 0.9966343045f, 0.9966185689f, + 0.9966027737f, 0.9965869784f, 0.9965711236f, 0.9965552688f, 0.9965393543f, + 0.9965233803f, 0.9965074062f, 0.9964913726f, 0.9964752793f, 0.9964591861f, + 0.9964430332f, 0.9964268804f, 0.9964106679f, 0.9963943958f, 0.9963781238f, + 0.9963617921f, 0.9963454604f, 0.9963290691f, 0.9963126183f, 0.9962961674f, + 0.9962796569f, 0.9962630868f, 0.9962465167f, 0.9962298870f, 0.9962132573f, + 0.9961965680f, 0.9961798191f, 0.9961630702f, 0.9961462617f, 0.9961294532f, + 0.9961125851f, 0.9960956573f, 0.9960787296f, 0.9960617423f, 0.9960446954f, + 0.9960276484f, 0.9960105419f, 0.9959934354f, 0.9959762692f, 0.9959590435f, + 0.9959418178f, 0.9959245324f, 0.9959072471f, 0.9958899021f, 0.9958724976f, + 0.9958550930f, 0.9958376288f, 0.9958201051f, 0.9958025813f, 0.9957849979f, + 0.9957674146f, 0.9957497716f, 0.9957320690f, 0.9957143664f, 0.9956966043f, + 0.9956788421f, 0.9956610203f, 0.9956431389f, 0.9956252575f, 0.9956073165f, + 0.9955893755f, 0.9955713153f, 0.9955533147f, 0.9955351949f, 0.9955170751f, + 0.9954989552f, 0.9954807758f, 0.9954625368f, 0.9954442382f, 0.9954259396f, + 0.9954076409f, 0.9953892231f, 0.9953708649f, 0.9953523874f, 0.9953339100f, + 0.9953153729f, 0.9952968359f, 0.9952782393f, 0.9952595830f, 0.9952409267f, + 0.9952222705f, 0.9952034950f, 0.9951847196f, 0.9951658845f, 0.9951470494f, + 0.9951281548f, 0.9951092601f, 0.9950903058f, 0.9950712919f, 0.9950522780f, + 0.9950332046f, 0.9950140715f, 0.9949949384f, 0.9949757457f, 0.9949565530f, + 0.9949373007f, 0.9949179888f, 0.9948986769f, 0.9948793054f, 0.9948599339f, + 0.9948405027f, 0.9948210120f, 0.9948015213f, 0.9947819710f, 0.9947624207f, + 0.9947427511f, 0.9947231412f, 0.9947034121f, 0.9946836829f, 0.9946639538f, + 0.9946441650f, 0.9946243167f, 0.9946044087f, 0.9945845008f, 0.9945645928f, + 0.9945445657f, 0.9945245385f, 0.9945045114f, 0.9944844246f, 0.9944642782f, + 0.9944441319f, 0.9944239259f, 0.9944036603f, 0.9943833947f, 0.9943630695f, + 0.9943427444f, 0.9943223596f, 0.9943019152f, 0.9942814708f, 0.9942609668f, + 0.9942404628f, 0.9942198992f, 0.9941992760f, 0.9941786528f, 0.9941579700f, + 0.9941372275f, 0.9941164851f, 0.9940956831f, 0.9940748811f, 0.9940540195f, + 0.9940330982f, 0.9940121770f, 0.9939911962f, 0.9939702153f, 0.9939491749f, + 0.9939280748f, 0.9939069748f, 0.9938858151f, 0.9938646555f, 0.9938433766f, + 0.9938221574f, 0.9938008189f, 0.9937794805f, 0.9937581420f, 0.9937367439f, + 0.9937152863f, 0.9936937690f, 0.9936722517f, 0.9936507344f, 0.9936291575f, + 0.9936075211f, 0.9935858250f, 0.9935641289f, 0.9935423732f, 0.9935206175f, + 0.9934988022f, 0.9934769869f, 0.9934550524f, 0.9934331775f, 0.9934111834f, + 0.9933891892f, 0.9933671951f, 0.9933451414f, 0.9933230281f, 0.9933008552f, + 0.9932786822f, 0.9932565093f, 0.9932342172f, 0.9932119250f, 0.9931896329f, + 0.9931672812f, 0.9931448698f, 0.9931224585f, 0.9930999875f, 0.9930774570f, + 0.9930549264f, 0.9930323362f, 0.9930097461f, 0.9929870963f, 0.9929643869f, + 0.9929416776f, 0.9929189086f, 0.9928961396f, 0.9928733110f, 0.9928504229f, + 0.9928275347f, 0.9928045869f, 0.9927815795f, 0.9927585721f, 0.9927355051f, + 0.9927124381f, 0.9926893115f, 0.9926661253f, 0.9926429391f, 0.9926196933f, + 0.9925964475f, 0.9925731421f, 0.9925497770f, 0.9925264120f, 0.9925029874f, + 0.9924795628f, 0.9924560189f, 0.9924325347f, 0.9924089313f, 0.9923853278f, + 0.9923617244f, 0.9923380613f, 0.9923143387f, 0.9922906160f, 0.9922668338f, + 0.9922429919f, 0.9922191501f, 0.9921952486f, 0.9921712875f, 0.9921473265f, + 0.9921233654f, 0.9920992851f, 0.9920752645f, 0.9920511246f, 0.9920269847f, + 0.9920027852f, 0.9919785857f, 0.9919543266f, 0.9919300079f, 0.9919056892f, + 0.9918813109f, 0.9918569326f, 0.9918324947f, 0.9918079972f, 0.9917834997f, + 0.9917589426f, 0.9917343855f, 0.9917097688f, 0.9916850924f, 0.9916604161f, + 0.9916356802f, 0.9916108847f, 0.9915860891f, 0.9915612340f, 0.9915363789f, + 0.9915114641f, 0.9914865494f, 0.9914615154f, 0.9914365411f, 0.9914114475f, + 0.9913863540f, 0.9913612604f, 0.9913360476f, 0.9913108349f, 0.9912856221f, + 0.9912603498f, 0.9912350178f, 0.9912096858f, 0.9911842942f, 0.9911588430f, + 0.9911333919f, 0.9911079407f, 0.9910823703f, 0.9910567999f, 0.9910312295f, + 0.9910055399f, 0.9909799099f, 0.9909541607f, 0.9909284115f, 0.9909026623f, + 0.9908767939f, 0.9908509254f, 0.9908250570f, 0.9907991290f, 0.9907731414f, + 0.9907471538f, 0.9907211065f, 0.9906949997f, 0.9906688929f, 0.9906427860f, + 0.9906165600f, 0.9905903339f, 0.9905641079f, 0.9905377626f, 0.9905114770f, + 0.9904850721f, 0.9904586673f, 0.9904322624f, 0.9904057384f, 0.9903792143f, + 0.9903526902f, 0.9903261065f, 0.9902994633f, 0.9902728200f, 0.9902461171f, + 0.9902193546f, 0.9901925921f, 0.9901658297f, 0.9901389480f, 0.9901120663f, + 0.9900851846f, 0.9900581837f, 0.9900312424f, 0.9900041819f, 0.9899771214f, + 0.9899500608f, 0.9899228811f, 0.9898957014f, 0.9898685217f, 0.9898412824f, + 0.9898139834f, 0.9897866845f, 0.9897593260f, 0.9897319674f, 0.9897044897f, + 0.9896770716f, 0.9896495342f, 0.9896219969f, 0.9895944595f, 0.9895668626f, + 0.9895392060f, 0.9895114899f, 0.9894837737f, 0.9894560575f, 0.9894282818f, + 0.9894004464f, 0.9893725514f, 0.9893446565f, 0.9893167019f, 0.9892887473f, + 0.9892607331f, 0.9892327189f, 0.9892046452f, 0.9891765118f, 0.9891483784f, + 0.9891201854f, 0.9890919328f, 0.9890636802f, 0.9890353680f, 0.9890070558f, + 0.9889786839f, 0.9889502525f, 0.9889218211f, 0.9888933301f, 0.9888648391f, + 0.9888362885f, 0.9888076782f, 0.9887790680f, 0.9887503982f, 0.9887216687f, + 0.9886929393f, 0.9886642098f, 0.9886353612f, 0.9886065125f, 0.9885776639f, + 0.9885487556f, 0.9885197878f, 0.9884908199f, 0.9884617925f, 0.9884327054f, + 0.9884036183f, 0.9883744717f, 0.9883453250f, 0.9883161187f, 0.9882868528f, + 0.9882575870f, 0.9882282615f, 0.9881988764f, 0.9881694913f, 0.9881401062f, + 0.9881106019f, 0.9880810976f, 0.9880515933f, 0.9880220294f, 0.9879924059f, + 0.9879627824f, 0.9879330993f, 0.9879033566f, 0.9878736138f, 0.9878438115f, + 0.9878140092f, 0.9877841473f, 0.9877542257f, 0.9877243042f, 0.9876943231f, + 0.9876643419f, 0.9876343012f, 0.9876042008f, 0.9875741005f, 0.9875439405f, + 0.9875137806f, 0.9874835014f, 0.9874532819f, 0.9874229431f, 0.9873926640f, + 0.9873622656f, 0.9873318672f, 0.9873014092f, 0.9872709513f, 0.9872404337f, + 0.9872098565f, 0.9871792793f, 0.9871486425f, 0.9871180058f, 0.9870873094f, + 0.9870565534f, 0.9870257974f, 0.9869949818f, 0.9869641662f, 0.9869332910f, + 0.9869023561f, 0.9868714213f, 0.9868404269f, 0.9868093729f, 0.9867783189f, + 0.9867472649f, 0.9867160916f, 0.9866849184f, 0.9866537452f, 0.9866225123f, + 0.9865912199f, 0.9865599275f, 0.9865285754f, 0.9864971638f, 0.9864657521f, + 0.9864342809f, 0.9864028096f, 0.9863712788f, 0.9863396883f, 0.9863080978f, + 0.9862764478f, 0.9862447977f, 0.9862130880f, 0.9861813188f, 0.9861495495f, + 0.9861177206f, 0.9860858321f, 0.9860539436f, 0.9860220551f, 0.9859900475f, + 0.9859580398f, 0.9859260321f, 0.9858939648f, 0.9858618379f, 0.9858297110f, + 0.9857975245f, 0.9857652783f, 0.9857330322f, 0.9857007265f, 0.9856684208f, + 0.9856360555f, 0.9856036305f, 0.9855712056f, 0.9855387211f, 0.9855062366f, + 0.9854736924f, 0.9854410887f, 0.9854084849f, 0.9853758216f, 0.9853431582f, + 0.9853103757f, 0.9852776527f, 0.9852448702f, 0.9852120280f, 0.9851791263f, + 0.9851462245f, 0.9851132631f, 0.9850803018f, 0.9850472808f, 0.9850142598f, + 0.9849811196f, 0.9849480391f, 0.9849148393f, 0.9848816395f, 0.9848484397f, + 0.9848151803f, 0.9847818613f, 0.9847484827f, 0.9847151041f, 0.9846817255f, + 0.9846482277f, 0.9846147895f, 0.9845812321f, 0.9845476747f, 0.9845140576f, + 0.9844804406f, 0.9844467640f, 0.9844130874f, 0.9843793511f, 0.9843455553f, + 0.9843117595f, 0.9842779040f, 0.9842439890f, 0.9842100739f, 0.9841761589f, + 0.9841421247f, 0.9841080904f, 0.9840740561f, 0.9840399623f, 0.9840058088f, + 0.9839715958f, 0.9839373827f, 0.9839031696f, 0.9838688970f, 0.9838345647f, + 0.9838002324f, 0.9837658405f, 0.9837313890f, 0.9836969376f, 0.9836624265f, + 0.9836278558f, 0.9835932851f, 0.9835587144f, 0.9835240245f, 0.9834893942f, + 0.9834546447f, 0.9834198952f, 0.9833850861f, 0.9833502769f, 0.9833154082f, + 0.9832805395f, 0.9832456112f, 0.9832106233f, 0.9831756353f, 0.9831405878f, + 0.9831054807f, 0.9830703735f, 0.9830352068f, 0.9830000401f, 0.9829648137f, + 0.9829295278f, 0.9828942418f, 0.9828588963f, 0.9828235507f, 0.9827881455f, + 0.9827526808f, 0.9827172160f, 0.9826816916f, 0.9826461673f, 0.9826105833f, + 0.9825749397f, 0.9825392962f, 0.9825035930f, 0.9824678898f, 0.9824321270f, + 0.9823963046f, 0.9823604822f, 0.9823246002f, 0.9822887182f, 0.9822527170f, + 0.9822167754f, 0.9821807146f, 0.9821447134f, 0.9821085930f, 0.9820724726f, + 0.9820362926f, 0.9820001125f, 0.9819638729f, 0.9819275737f, 0.9818912745f, + 0.9818549156f, 0.9818185568f, 0.9817821383f, 0.9817457199f, 0.9817091823f, + 0.9816727042f, 0.9816361070f, 0.9815995097f, 0.9815629125f, 0.9815262556f, + 0.9814895391f, 0.9814527631f, 0.9814159870f, 0.9813792109f, 0.9813423157f, + 0.9813054800f, 0.9812685251f, 0.9812315702f, 0.9811946154f, 0.9811575413f, + 0.9811204672f, 0.9810833931f, 0.9810462594f, 0.9810090661f, 0.9809718728f, + 0.9809346199f, 0.9808973670f, 0.9808599949f, 0.9808226824f, 0.9807852507f, + 0.9807478786f, 0.9807103872f, 0.9806728959f, 0.9806353450f, 0.9805977941f, + 0.9805601835f, 0.9805225134f, 0.9804848433f, 0.9804471731f, 0.9804093838f, + 0.9803715944f, 0.9803338051f, 0.9802958965f, 0.9802580476f, 0.9802200794f, + 0.9801821113f, 0.9801441431f, 0.9801061153f, 0.9800680280f, 0.9800298810f, + 0.9799917340f, 0.9799535871f, 0.9799153805f, 0.9798771143f, 0.9798387885f, + 0.9798004627f, 0.9797621369f, 0.9797236919f, 0.9796853065f, 0.9796468019f, + 0.9796082973f, 0.9795697927f, 0.9795311689f, 0.9794925451f, 0.9794539213f, + 0.9794152379f, 0.9793764949f, 0.9793377519f, 0.9792989492f, 0.9792601466f, + 0.9792212248f, 0.9791823626f, 0.9791434407f, 0.9791044593f, 0.9790654182f, + 0.9790263772f, 0.9789872766f, 0.9789481759f, 0.9789090157f, 0.9788698554f, + 0.9788305759f, 0.9787913561f, 0.9787520170f, 0.9787126780f, 0.9786733389f, + 0.9786339402f, 0.9785944819f, 0.9785550237f, 0.9785155058f, 0.9784759283f, + 0.9784363508f, 0.9783967137f, 0.9783570766f, 0.9783173800f, 0.9782776237f, + 0.9782378674f, 0.9781980515f, 0.9781582355f, 0.9781183600f, 0.9780784249f, + 0.9780384898f, 0.9779984951f, 0.9779585004f, 0.9779184461f, 0.9778783321f, + 0.9778382182f, 0.9777980447f, 0.9777578712f, 0.9777176380f, 0.9776773453f, + 0.9776370525f, 0.9775967002f, 0.9775563478f, 0.9775159359f, 0.9774754643f, + 0.9774349928f, 0.9773944616f, 0.9773538709f, 0.9773132801f, 0.9772726893f, + 0.9772319794f, 0.9771913290f, 0.9771505594f, 0.9771097898f, 0.9770689607f, + 0.9770281315f, 0.9769872427f, 0.9769463539f, 0.9769054055f, 0.9768643975f, + 0.9768233895f, 0.9767823219f, 0.9767411947f, 0.9767000675f, 0.9766589403f, + 0.9766176939f, 0.9765764475f, 0.9765352011f, 0.9764938951f, 0.9764525294f, + 0.9764111638f, 0.9763697386f, 0.9763282537f, 0.9762867689f, 0.9762452841f, + 0.9762036800f, 0.9761620760f, 0.9761204720f, 0.9760788083f, 0.9760370851f, + 0.9759953618f, 0.9759535789f, 0.9759117365f, 0.9758698940f, 0.9758279920f, + 0.9757860899f, 0.9757441282f, 0.9757021070f, 0.9756600857f, 0.9756180048f, + 0.9755759239f, 0.9755337834f, 0.9754916430f, 0.9754493833f, 0.9754071832f, + 0.9753648639f, 0.9753225446f, 0.9752802253f, 0.9752378464f, 0.9751954079f, + 0.9751529694f, 0.9751104712f, 0.9750679135f, 0.9750253558f, 0.9749827385f, + 0.9749401212f, 0.9748974442f, 0.9748547077f, 0.9748119712f, 0.9747691751f, + 0.9747263789f, 0.9746835232f, 0.9746406078f, 0.9745976925f, 0.9745547175f, + 0.9745117426f, 0.9744687080f, 0.9744256139f, 0.9743825197f, 0.9743393660f, + 0.9742962122f, 0.9742529988f, 0.9742097259f, 0.9741664529f, 0.9741231203f, + 0.9740797877f, 0.9740363955f, 0.9739929438f, 0.9739494920f, 0.9739059806f, + 0.9738624692f, 0.9738188982f, 0.9737752676f, 0.9737316370f, 0.9736879468f, + 0.9736442566f, 0.9736005068f, 0.9735566974f, 0.9735128880f, 0.9734690189f, + 0.9734251499f, 0.9733812213f, 0.9733372331f, 0.9732932448f, 0.9732491970f, + 0.9732051492f, 0.9731610417f, 0.9731168747f, 0.9730727077f, 0.9730284810f, + 0.9729842544f, 0.9729399681f, 0.9728956223f, 0.9728512764f, 0.9728068709f, + 0.9727624655f, 0.9727180004f, 0.9726734757f, 0.9726289511f, 0.9725843668f, + 0.9725397825f, 0.9724951386f, 0.9724504352f, 0.9724057317f, 0.9723609686f, + 0.9723162055f, 0.9722713232f, 0.9722265005f, 0.9721816182f, 0.9721366763f, + 0.9720917344f, 0.9720467329f, 0.9720016718f, 0.9719566107f, 0.9719114900f, + 0.9718663096f, 0.9718211293f, 0.9717759490f, 0.9717307091f, 0.9716854095f, + 0.9716400504f, 0.9715946913f, 0.9715493321f, 0.9715039134f, 0.9714584351f, + 0.9714128971f, 0.9713673592f, 0.9713218212f, 0.9712762237f, 0.9712305665f, + 0.9711848497f, 0.9711391330f, 0.9710934162f, 0.9710476398f, 0.9710018039f, + 0.9709559083f, 0.9709100127f, 0.9708641171f, 0.9708181620f, 0.9707721472f, + 0.9707261324f, 0.9706799984f, 0.9706339240f, 0.9705877900f, 0.9705415964f, + 0.9704954028f, 0.9704491496f, 0.9704028368f, 0.9703565240f, 0.9703101516f, + 0.9702637792f, 0.9702173471f, 0.9701708555f, 0.9701243639f, 0.9700778127f, + 0.9700312614f, 0.9699846506f, 0.9699379802f, 0.9698913097f, 0.9698445797f, + 0.9697978497f, 0.9697510600f, 0.9697042704f, 0.9696573615f, 0.9696105123f, + 0.9695635438f, 0.9695165753f, 0.9694696069f, 0.9694225788f, 0.9693754911f, + 0.9693284035f, 0.9692812562f, 0.9692340493f, 0.9691868424f, 0.9691395760f, + 0.9690923095f, 0.9690449834f, 0.9689975977f, 0.9689502120f, 0.9689028263f, + 0.9688553214f, 0.9688078165f, 0.9687603116f, 0.9687127471f, 0.9686651230f, + 0.9686174989f, 0.9685698152f, 0.9685220718f, 0.9684743285f, 0.9684265852f, + 0.9683787227f, 0.9683308601f, 0.9682829976f, 0.9682350755f, 0.9681870937f, + 0.9681391120f, 0.9680910707f, 0.9680429697f, 0.9679948688f, 0.9679467678f, + 0.9678986073f, 0.9678503871f, 0.9678021073f, 0.9677538276f, 0.9677054882f, + 0.9676571488f, 0.9676087499f, 0.9675603509f, 0.9675118923f, 0.9674633741f, + 0.9674148560f, 0.9673662782f, 0.9673177004f, 0.9672690630f, 0.9672203660f, + 0.9671716690f, 0.9671229124f, 0.9670741558f, 0.9670253396f, 0.9669764638f, + 0.9669275880f, 0.9668786526f, 0.9668297172f, 0.9667807221f, 0.9667316675f, + 0.9666826129f, 0.9666334987f, 0.9665843844f, 0.9665352106f, 0.9664859772f, + 0.9664367437f, 0.9663874507f, 0.9663381577f, 0.9662888050f, 0.9662394524f, + 0.9661899805f, 0.9661405683f, 0.9660910368f, 0.9660415053f, 0.9659919739f, + 0.9659423828f, 0.9658927321f, 0.9658430815f, 0.9657933712f, 0.9657436013f, + 0.9656938314f, 0.9656440020f, 0.9655941725f, 0.9655442834f, 0.9654943943f, + 0.9654444456f, 0.9653944373f, 0.9653444290f, 0.9652943611f, 0.9652442336f, + 0.9651941061f, 0.9651439786f, 0.9650937319f, 0.9650435448f, 0.9649932384f, + 0.9649429321f, 0.9648926258f, 0.9648422003f, 0.9647917747f, 0.9647413492f, + 0.9646908641f, 0.9646403193f, 0.9645897746f, 0.9645391703f, 0.9644885659f, + 0.9644379020f, 0.9643872380f, 0.9643364549f, 0.9642857313f, 0.9642348886f, + 0.9641840458f, 0.9641332030f, 0.9640823007f, 0.9640313387f, 0.9639803171f, + 0.9639292955f, 0.9638782740f, 0.9638271928f, 0.9637760520f, 0.9637249112f, + 0.9636737108f, 0.9636224508f, 0.9635711908f, 0.9635199308f, 0.9634685516f, + 0.9634172320f, 0.9633657932f, 0.9633143544f, 0.9632628560f, 0.9632113576f, + 0.9631597996f, 0.9631082416f, 0.9630566239f, 0.9630049467f, 0.9629532695f, + 0.9629015326f, 0.9628497958f, 0.9627979994f, 0.9627461433f, 0.9626942873f, + 0.9626423717f, 0.9625904560f, 0.9625384808f, 0.9624864459f, 0.9624344110f, + 0.9623823166f, 0.9623302221f, 0.9622780681f, 0.9622258544f, 0.9621736407f, + 0.9621214271f, 0.9620690942f, 0.9620167613f, 0.9619644284f, 0.9619120359f, + 0.9618595839f, 0.9618071318f, 0.9617546201f, 0.9617020488f, 0.9616494775f, + 0.9615969062f, 0.9615442157f, 0.9614915848f, 0.9614388347f, 0.9613860846f, + 0.9613332748f, 0.9612804651f, 0.9612276554f, 0.9611747265f, 0.9611217976f, + 0.9610688090f, 0.9610158205f, 0.9609627724f, 0.9609097242f, 0.9608566165f, + 0.9608035088f, 0.9607503414f, 0.9606971145f, 0.9606438875f, 0.9605906010f, + 0.9605372548f, 0.9604839087f, 0.9604305029f, 0.9603770971f, 0.9603236318f, + 0.9602701664f, 0.9602166414f, 0.9601630569f, 0.9601094723f, 0.9600558281f, + 0.9600021243f, 0.9599484205f, 0.9598947167f, 0.9598408937f, 0.9597871304f, + 0.9597332478f, 0.9596793652f, 0.9596254826f, 0.9595714808f, 0.9595175385f, + 0.9594634771f, 0.9594094753f, 0.9593553543f, 0.9593012333f, 0.9592470527f, + 0.9591928720f, 0.9591386318f, 0.9590843320f, 0.9590300322f, 0.9589757323f, + 0.9589213133f, 0.9588668942f, 0.9588124752f, 0.9587579966f, 0.9587034583f, + 0.9586489201f, 0.9585943222f, 0.9585397243f, 0.9584850669f, 0.9584303498f, + 0.9583756328f, 0.9583208561f, 0.9582660794f, 0.9582112432f, 0.9581563473f, + 0.9581014514f, 0.9580464959f, 0.9579915404f, 0.9579365253f, 0.9578815103f, + 0.9578263760f, 0.9577713013f, 0.9577161670f, 0.9576609731f, 0.9576057196f, + 0.9575504661f, 0.9574952126f, 0.9574398398f, 0.9573845267f, 0.9573290944f, + 0.9572736621f, 0.9572182298f, 0.9571626782f, 0.9571071863f, 0.9570515752f, + 0.9569959641f, 0.9569403529f, 0.9568846822f, 0.9568289518f, 0.9567731619f, + 0.9567174315f, 0.9566615820f, 0.9566057324f, 0.9565498233f, 0.9564939141f, + 0.9564379454f, 0.9563819766f, 0.9563259482f, 0.9562698603f, 0.9562137723f, + 0.9561576247f, 0.9561014771f, 0.9560452700f, 0.9559890032f, 0.9559327364f, + 0.9558764100f, 0.9558200836f, 0.9557636976f, 0.9557072520f, 0.9556508064f, + 0.9555943012f, 0.9555377960f, 0.9554812312f, 0.9554246664f, 0.9553680420f, + 0.9553113580f, 0.9552546740f, 0.9551979303f, 0.9551411867f, 0.9550843239f, + 0.9550275207f, 0.9549706578f, 0.9549137354f, 0.9548567533f, 0.9547998309f, + 0.9547427893f, 0.9546858072f, 0.9546286464f, 0.9545715451f, 0.9545143843f, + 0.9544572234f, 0.9543999434f, 0.9543427229f, 0.9542854428f, 0.9542281032f, + 0.9541707039f, 0.9541133046f, 0.9540559053f, 0.9539984465f, 0.9539408684f, + 0.9538833499f, 0.9538258314f, 0.9537681937f, 0.9537104964f, 0.9536528587f, + 0.9535951614f, 0.9535374045f, 0.9534795880f, 0.9534217715f, 0.9533639550f, + 0.9533060789f, 0.9532480836f, 0.9531901479f, 0.9531321526f, 0.9530741572f, + 0.9530160427f, 0.9529579282f, 0.9528998137f, 0.9528416395f, 0.9527834058f, + 0.9527251720f, 0.9526669383f, 0.9526086450f, 0.9525502324f, 0.9524918795f, + 0.9524334669f, 0.9523750544f, 0.9523165226f, 0.9522579908f, 0.9521994591f, + 0.9521408677f, 0.9520822167f, 0.9520235658f, 0.9519648552f, 0.9519061446f, + 0.9518473148f, 0.9517885447f, 0.9517297149f, 0.9516708851f, 0.9516119361f, + 0.9515529871f, 0.9514940381f, 0.9514350295f, 0.9513760209f, 0.9513168931f, + 0.9512577653f, 0.9511986375f, 0.9511393905f, 0.9510802031f, 0.9510209560f, + 0.9509617090f, 0.9509023428f, 0.9508429766f, 0.9507836103f, 0.9507241845f, + 0.9506646395f, 0.9506051540f, 0.9505456686f, 0.9504860640f, 0.9504265189f, + 0.9503667951f, 0.9503071308f, 0.9502474666f, 0.9501876831f, 0.9501278996f, + 0.9500681162f, 0.9500082731f, 0.9499483705f, 0.9498884082f, 0.9498285055f, + 0.9497684836f, 0.9497084618f, 0.9496483803f, 0.9495882988f, 0.9495282173f, + 0.9494680166f, 0.9494078159f, 0.9493475556f, 0.9492872953f, 0.9492269754f, + 0.9491666555f, 0.9491062760f, 0.9490458965f, 0.9489854574f, 0.9489249587f, + 0.9488644600f, 0.9488039017f, 0.9487432837f, 0.9486826658f, 0.9486220479f, + 0.9485613704f, 0.9485006332f, 0.9484398365f, 0.9483790398f, 0.9483182430f, + 0.9482573271f, 0.9481964707f, 0.9481355548f, 0.9480745792f, 0.9480136037f, + 0.9479525089f, 0.9478914738f, 0.9478303790f, 0.9477692246f, 0.9477080107f, + 0.9476468563f, 0.9475855827f, 0.9475243092f, 0.9474629760f, 0.9474016428f, + 0.9473402500f, 0.9472788572f, 0.9472173452f, 0.9471558928f, 0.9470943809f, + 0.9470328093f, 0.9469711781f, 0.9469095469f, 0.9468479156f, 0.9467862248f, + 0.9467244744f, 0.9466627240f, 0.9466009140f, 0.9465391040f, 0.9464771748f, + 0.9464153051f, 0.9463533759f, 0.9462913871f, 0.9462293386f, 0.9461672902f, + 0.9461052418f, 0.9460431337f, 0.9459809661f, 0.9459187388f, 0.9458565712f, + 0.9457943439f, 0.9457319975f, 0.9456696510f, 0.9456073046f, 0.9455449581f, + 0.9454824924f, 0.9454200268f, 0.9453575611f, 0.9452950358f, 0.9452323914f, + 0.9451698065f, 0.9451072216f, 0.9450445175f, 0.9449817538f, 0.9449190497f, + 0.9448562860f, 0.9447935224f, 0.9447305799f, 0.9446677566f, 0.9446048141f, + 0.9445419312f, 0.9444789290f, 0.9444158673f, 0.9443528056f, 0.9442897439f, + 0.9442265630f, 0.9441634417f, 0.9441002607f, 0.9440370202f, 0.9439737797f, + 0.9439104795f, 0.9438471198f, 0.9437837601f, 0.9437203407f, 0.9436569214f, + 0.9435934424f, 0.9435299635f, 0.9434664249f, 0.9434028268f, 0.9433392286f, + 0.9432755709f, 0.9432118535f, 0.9431481957f, 0.9430844188f, 0.9430206418f, + 0.9429568648f, 0.9428929687f, 0.9428290725f, 0.9427651763f, 0.9427011609f, + 0.9426372051f, 0.9425731897f, 0.9425091743f, 0.9424450397f, 0.9423809052f, + 0.9423167109f, 0.9422525764f, 0.9421882629f, 0.9421240091f, 0.9420597553f, + 0.9419953823f, 0.9419310689f, 0.9418665767f, 0.9418021441f, 0.9417377114f, + 0.9416731596f, 0.9416086078f, 0.9415440559f, 0.9414794445f, 0.9414148331f, + 0.9413501024f, 0.9412853718f, 0.9412206411f, 0.9411557913f, 0.9410910010f, + 0.9410261512f, 0.9409613013f, 0.9408963919f, 0.9408313632f, 0.9407663941f, + 0.9407013655f, 0.9406363368f, 0.9405711889f, 0.9405060410f, 0.9404408932f, + 0.9403757453f, 0.9403104186f, 0.9402451515f, 0.9401798844f, 0.9401145577f, + 0.9400491118f, 0.9399837255f, 0.9399183393f, 0.9398528337f, 0.9397872686f, + 0.9397217631f, 0.9396561980f, 0.9395905733f, 0.9395248890f, 0.9394592047f, + 0.9393935204f, 0.9393277764f, 0.9392619133f, 0.9391961098f, 0.9391302466f, + 0.9390643835f, 0.9389984012f, 0.9389324784f, 0.9388664961f, 0.9388004541f, + 0.9387343526f, 0.9386682510f, 0.9386021495f, 0.9385359883f, 0.9384697676f, + 0.9384035468f, 0.9383372664f, 0.9382709861f, 0.9382045865f, 0.9381381869f, + 0.9380718470f, 0.9380053878f, 0.9379388690f, 0.9378723502f, 0.9378058314f, + 0.9377392530f, 0.9376726151f, 0.9376059771f, 0.9375392795f, 0.9374725819f, + 0.9374057651f, 0.9373390079f, 0.9372721910f, 0.9372053146f, 0.9371384382f, + 0.9370715022f, 0.9370045662f, 0.9369375706f, 0.9368704557f, 0.9368034005f, + 0.9367363453f, 0.9366692305f, 0.9366020560f, 0.9365348220f, 0.9364675879f, + 0.9364003539f, 0.9363330007f, 0.9362656474f, 0.9361982942f, 0.9361308813f, + 0.9360634685f, 0.9359959364f, 0.9359284639f, 0.9358608723f, 0.9357932806f, + 0.9357256889f, 0.9356580377f, 0.9355903864f, 0.9355226755f, 0.9354548454f, + 0.9353870749f, 0.9353193045f, 0.9352513552f, 0.9351834655f, 0.9351155758f, + 0.9350476265f, 0.9349796772f, 0.9349115491f, 0.9348435402f, 0.9347754121f, + 0.9347072840f, 0.9346390963f, 0.9345709085f, 0.9345027208f, 0.9344344735f, + 0.9343661070f, 0.9342977405f, 0.9342294335f, 0.9341609478f, 0.9340925217f, + 0.9340240955f, 0.9339555502f, 0.9338870645f, 0.9338183999f, 0.9337497950f, + 0.9336811900f, 0.9336125255f, 0.9335437417f, 0.9334750175f, 0.9334062338f, + 0.9333374500f, 0.9332685471f, 0.9331996441f, 0.9331307411f, 0.9330618382f, + 0.9329927564f, 0.9329237938f, 0.9328547120f, 0.9327856302f, 0.9327164888f, + 0.9326473475f, 0.9325781465f, 0.9325089455f, 0.9324396253f, 0.9323703051f, + 0.9323009849f, 0.9322316647f, 0.9321621656f, 0.9320927858f, 0.9320232868f, + 0.9319538474f, 0.9318842292f, 0.9318146706f, 0.9317451119f, 0.9316754341f, + 0.9316057563f, 0.9315360188f, 0.9314662814f, 0.9313965440f, 0.9313266873f, + 0.9312568307f, 0.9311869740f, 0.9311170578f, 0.9310470819f, 0.9309771061f, + 0.9309071302f, 0.9308370352f, 0.9307669401f, 0.9306968451f, 0.9306266904f, + 0.9305564761f, 0.9304862618f, 0.9304159880f, 0.9303457141f, 0.9302753806f, + 0.9302049875f, 0.9301345944f, 0.9300642014f, 0.9299937487f, 0.9299231768f, + 0.9298526645f, 0.9297821522f, 0.9297115803f, 0.9296408892f, 0.9295701981f, + 0.9294995070f, 0.9294288158f, 0.9293580651f, 0.9292871952f, 0.9292163849f, + 0.9291455150f, 0.9290745258f, 0.9290035963f, 0.9289326668f, 0.9288616776f, + 0.9287906289f, 0.9287195206f, 0.9286484122f, 0.9285773039f, 0.9285060167f, + 0.9284348488f, 0.9283636212f, 0.9282923341f, 0.9282210469f, 0.9281496406f, + 0.9280782938f, 0.9280068874f, 0.9279353619f, 0.9278638959f, 0.9277923703f, + 0.9277208447f, 0.9276492596f, 0.9275776148f, 0.9275059700f, 0.9274342656f, + 0.9273625016f, 0.9272907376f, 0.9272189736f, 0.9271471500f, 0.9270752668f, + 0.9270033836f, 0.9269314408f, 0.9268594980f, 0.9267874360f, 0.9267154336f, + 0.9266433716f, 0.9265712500f, 0.9264991283f, 0.9264269471f, 0.9263547659f, + 0.9262825251f, 0.9262102246f, 0.9261379242f, 0.9260655642f, 0.9259932041f, + 0.9259208441f, 0.9258483648f, 0.9257758856f, 0.9257034063f, 0.9256308675f, + 0.9255582094f, 0.9254856110f, 0.9254130125f, 0.9253403544f, 0.9252675772f, + 0.9251948595f, 0.9251220822f, 0.9250492454f, 0.9249763489f, 0.9249035120f, + 0.9248306155f, 0.9247576594f, 0.9246846437f, 0.9246116281f, 0.9245385528f, + 0.9244654775f, 0.9243923426f, 0.9243192077f, 0.9242460132f, 0.9241728187f, + 0.9240995049f, 0.9240261912f, 0.9239528775f, 0.9238795638f, 0.9238061309f, + 0.9237326980f, 0.9236592650f, 0.9235857725f, 0.9235121608f, 0.9234386086f, + 0.9233650565f, 0.9232914448f, 0.9232177138f, 0.9231440425f, 0.9230703115f, + 0.9229965806f, 0.9229227304f, 0.9228488803f, 0.9227750301f, 0.9227011204f, + 0.9226271510f, 0.9225531816f, 0.9224792123f, 0.9224051833f, 0.9223310351f, + 0.9222569466f, 0.9221828580f, 0.9221087098f, 0.9220344424f, 0.9219601750f, + 0.9218859076f, 0.9218116403f, 0.9217373133f, 0.9216628671f, 0.9215884805f, + 0.9215140343f, 0.9214395285f, 0.9213650227f, 0.9212905169f, 0.9212159514f, + 0.9211413264f, 0.9210666418f, 0.9209919572f, 0.9209172726f, 0.9208424687f, + 0.9207676649f, 0.9206928611f, 0.9206180573f, 0.9205431938f, 0.9204682112f, + 0.9203932881f, 0.9203183055f, 0.9202432036f, 0.9201681614f, 0.9200931191f, + 0.9200180173f, 0.9199428558f, 0.9198676348f, 0.9197924137f, 0.9197171330f, + 0.9196417928f, 0.9195665121f, 0.9194911718f, 0.9194157720f, 0.9193403721f, + 0.9192648530f, 0.9191893935f, 0.9191138744f, 0.9190382361f, 0.9189626575f, + 0.9188870788f, 0.9188113809f, 0.9187357426f, 0.9186599255f, 0.9185841680f, + 0.9185084105f, 0.9184325337f, 0.9183566570f, 0.9182807803f, 0.9182048440f, + 0.9181289077f, 0.9180528522f, 0.9179768562f, 0.9179008007f, 0.9178246260f, + 0.9177485108f, 0.9176723361f, 0.9175961614f, 0.9175199270f, 0.9174436331f, + 0.9173673391f, 0.9172909856f, 0.9172146320f, 0.9171382189f, 0.9170617461f, + 0.9169853330f, 0.9169088006f, 0.9168322086f, 0.9167556763f, 0.9166790843f, + 0.9166024327f, 0.9165257215f, 0.9164490104f, 0.9163722992f, 0.9162955284f, + 0.9162186384f, 0.9161418676f, 0.9160649776f, 0.9159880877f, 0.9159110785f, + 0.9158341289f, 0.9157571197f, 0.9156800508f, 0.9156029224f, 0.9155258536f, + 0.9154487252f, 0.9153715372f, 0.9152942896f, 0.9152170420f, 0.9151397943f, + 0.9150624871f, 0.9149850607f, 0.9149076939f, 0.9148303270f, 0.9147529006f, + 0.9146753550f, 0.9145978689f, 0.9145203233f, 0.9144427180f, 0.9143650532f, + 0.9142874479f, 0.9142097831f, 0.9141320586f, 0.9140542746f, 0.9139764905f, + 0.9138986468f, 0.9138208032f, 0.9137428999f, 0.9136649966f, 0.9135870337f, + 0.9135090709f, 0.9134309888f, 0.9133529663f, 0.9132748842f, 0.9131968021f, + 0.9131186604f, 0.9130403996f, 0.9129621983f, 0.9128839374f, 0.9128056169f, + 0.9127272964f, 0.9126489758f, 0.9125705957f, 0.9124921560f, 0.9124136567f, + 0.9123351574f, 0.9122566581f, 0.9121780396f, 0.9120994806f, 0.9120208621f, + 0.9119422436f, 0.9118635654f, 0.9117847681f, 0.9117060304f, 0.9116272330f, + 0.9115483761f, 0.9114695191f, 0.9113906622f, 0.9113117456f, 0.9112327695f, + 0.9111537337f, 0.9110747576f, 0.9109956622f, 0.9109165668f, 0.9108374119f, + 0.9107582569f, 0.9106791019f, 0.9105998874f, 0.9105205536f, 0.9104412794f, + 0.9103619456f, 0.9102825522f, 0.9102031589f, 0.9101237655f, 0.9100443125f, + 0.9099647999f, 0.9098852277f, 0.9098057151f, 0.9097261429f, 0.9096464515f, + 0.9095667601f, 0.9094871283f, 0.9094073772f, 0.9093276262f, 0.9092478156f, + 0.9091679454f, 0.9090881348f, 0.9090082645f, 0.9089282751f, 0.9088482857f, + 0.9087683558f, 0.9086883068f, 0.9086081982f, 0.9085280895f, 0.9084479809f, + 0.9083678722f, 0.9082875848f, 0.9082073569f, 0.9081271291f, 0.9080468416f, + 0.9079664350f, 0.9078860879f, 0.9078057408f, 0.9077252746f, 0.9076448083f, + 0.9075642824f, 0.9074838161f, 0.9074032307f, 0.9073225856f, 0.9072419405f, + 0.9071612954f, 0.9070806503f, 0.9069998264f, 0.9069191217f, 0.9068382978f, + 0.9067574739f, 0.9066765904f, 0.9065957069f, 0.9065147638f, 0.9064338207f, + 0.9063527584f, 0.9062717557f, 0.9061906934f, 0.9061096311f, 0.9060284495f, + 0.9059472680f, 0.9058660865f, 0.9057848454f, 0.9057035446f, 0.9056223035f, + 0.9055409431f, 0.9054595828f, 0.9053781629f, 0.9052967429f, 0.9052152634f, + 0.9051337838f, 0.9050522447f, 0.9049706459f, 0.9048891068f, 0.9048074484f, + 0.9047257304f, 0.9046440721f, 0.9045623541f, 0.9044806361f, 0.9043987393f, + 0.9043169618f, 0.9042350650f, 0.9041532278f, 0.9040712714f, 0.9039892554f, + 0.9039072990f, 0.9038252831f, 0.9037431479f, 0.9036610723f, 0.9035789371f, + 0.9034968019f, 0.9034146070f, 0.9033323526f, 0.9032500982f, 0.9031678438f, + 0.9030854702f, 0.9030030966f, 0.9029207230f, 0.9028382897f, 0.9027558565f, + 0.9026733041f, 0.9025907516f, 0.9025082588f, 0.9024255872f, 0.9023429751f, + 0.9022603035f, 0.9021776319f, 0.9020949006f, 0.9020121098f, 0.9019293189f, + 0.9018465281f, 0.9017636180f, 0.9016807079f, 0.9015977979f, 0.9015148878f, + 0.9014319181f, 0.9013488293f, 0.9012658000f, 0.9011827111f, 0.9010995030f, + 0.9010163546f, 0.9009332061f, 0.9008499980f, 0.9007667303f, 0.9006834030f, + 0.9006000757f, 0.9005167484f, 0.9004333019f, 0.9003499150f, 0.9002664685f, + 0.9001829624f, 0.9000994563f, 0.9000158906f, 0.8999322653f, 0.8998486996f, + 0.8997650146f, 0.8996813297f, 0.8995975852f, 0.8995138407f, 0.8994300961f, + 0.8993462324f, 0.8992623687f, 0.8991785049f, 0.8990945816f, 0.8990105987f, + 0.8989266157f, 0.8988426328f, 0.8987585902f, 0.8986744285f, 0.8985903263f, + 0.8985061646f, 0.8984220028f, 0.8983377814f, 0.8982535005f, 0.8981692791f, + 0.8980849385f, 0.8980005383f, 0.8979161978f, 0.8978317976f, 0.8977473378f, + 0.8976628184f, 0.8975782990f, 0.8974937797f, 0.8974092007f, 0.8973245621f, + 0.8972399235f, 0.8971552253f, 0.8970705271f, 0.8969857693f, 0.8969010115f, + 0.8968161941f, 0.8967313766f, 0.8966464400f, 0.8965615630f, 0.8964766264f, + 0.8963916302f, 0.8963065743f, 0.8962215781f, 0.8961365223f, 0.8960514069f, + 0.8959662318f, 0.8958810568f, 0.8957958817f, 0.8957106471f, 0.8956252933f, + 0.8955399990f, 0.8954547048f, 0.8953693509f, 0.8952839375f, 0.8951984644f, + 0.8951129913f, 0.8950275183f, 0.8949419260f, 0.8948563933f, 0.8947708011f, + 0.8946851492f, 0.8945994973f, 0.8945137858f, 0.8944280744f, 0.8943423033f, + 0.8942564726f, 0.8941706419f, 0.8940847516f, 0.8939988613f, 0.8939129710f, + 0.8938269615f, 0.8937409520f, 0.8936549425f, 0.8935688734f, 0.8934827447f, + 0.8933966756f, 0.8933104873f, 0.8932243586f, 0.8931380510f, 0.8930518031f, + 0.8929655552f, 0.8928791285f, 0.8927928209f, 0.8927064538f, 0.8926200271f, + 0.8925336003f, 0.8924470544f, 0.8923605084f, 0.8922740221f, 0.8921873569f, + 0.8921007514f, 0.8920140862f, 0.8919274211f, 0.8918407559f, 0.8917539120f, + 0.8916671872f, 0.8915803432f, 0.8914934397f, 0.8914065957f, 0.8913196921f, + 0.8912327290f, 0.8911457658f, 0.8910587430f, 0.8909716606f, 0.8908846378f, + 0.8907974958f, 0.8907103539f, 0.8906231523f, 0.8905359507f, 0.8904487491f, + 0.8903614283f, 0.8902741075f, 0.8901867867f, 0.8900994658f, 0.8900119662f, + 0.8899245858f, 0.8898370862f, 0.8897495866f, 0.8896620274f, 0.8895744681f, + 0.8894868493f, 0.8893992305f, 0.8893115520f, 0.8892238736f, 0.8891361356f, + 0.8890483975f, 0.8889605403f, 0.8888726830f, 0.8887848854f, 0.8886969686f, + 0.8886089921f, 0.8885210752f, 0.8884330392f, 0.8883450627f, 0.8882569671f, + 0.8881688714f, 0.8880807757f, 0.8879926205f, 0.8879043460f, 0.8878161311f, + 0.8877279162f, 0.8876396418f, 0.8875512481f, 0.8874629140f, 0.8873745799f, + 0.8872861266f, 0.8871976137f, 0.8871091604f, 0.8870206475f, 0.8869321346f, + 0.8868435025f, 0.8867549300f, 0.8866662383f, 0.8865776062f, 0.8864888549f, + 0.8864001036f, 0.8863113523f, 0.8862225413f, 0.8861336708f, 0.8860448003f, + 0.8859558702f, 0.8858669400f, 0.8857779503f, 0.8856889606f, 0.8855999112f, + 0.8855108619f, 0.8854217529f, 0.8853325844f, 0.8852434158f, 0.8851542473f, + 0.8850649595f, 0.8849757314f, 0.8848864436f, 0.8847970963f, 0.8847077489f, + 0.8846183419f, 0.8845288754f, 0.8844394684f, 0.8843499422f, 0.8842604160f, + 0.8841708302f, 0.8840812445f, 0.8839916587f, 0.8839019537f, 0.8838122487f, + 0.8837225437f, 0.8836327791f, 0.8835430145f, 0.8834531903f, 0.8833633661f, + 0.8832734823f, 0.8831835389f, 0.8830935955f, 0.8830035925f, 0.8829135299f, + 0.8828235269f, 0.8827334642f, 0.8826433420f, 0.8825532198f, 0.8824629784f, + 0.8823727965f, 0.8822825551f, 0.8821922541f, 0.8821019530f, 0.8820116520f, + 0.8819212914f, 0.8818308711f, 0.8817403913f, 0.8816499114f, 0.8815594316f, + 0.8814688921f, 0.8813782930f, 0.8812877536f, 0.8811970949f, 0.8811064959f, + 0.8810157180f, 0.8809249997f, 0.8808342814f, 0.8807434440f, 0.8806526065f, + 0.8805617690f, 0.8804708719f, 0.8803799748f, 0.8802889585f, 0.8801980019f, + 0.8801069856f, 0.8800159693f, 0.8799248338f, 0.8798337579f, 0.8797426224f, + 0.8796514273f, 0.8795601726f, 0.8794689178f, 0.8793776631f, 0.8792863488f, + 0.8791949749f, 0.8791036010f, 0.8790122271f, 0.8789207935f, 0.8788293004f, + 0.8787378073f, 0.8786462545f, 0.8785547018f, 0.8784630895f, 0.8783714771f, + 0.8782798052f, 0.8781881332f, 0.8780963421f, 0.8780046105f, 0.8779128194f, + 0.8778209686f, 0.8777290583f, 0.8776372075f, 0.8775452971f, 0.8774533868f, + 0.8773613572f, 0.8772693276f, 0.8771772981f, 0.8770852089f, 0.8769930005f, + 0.8769009113f, 0.8768087029f, 0.8767165542f, 0.8766242862f, 0.8765319586f, + 0.8764396906f, 0.8763473630f, 0.8762549162f, 0.8761625290f, 0.8760700822f, + 0.8759776354f, 0.8758851290f, 0.8757925630f, 0.8756999969f, 0.8756074309f, + 0.8755147457f, 0.8754220605f, 0.8753293753f, 0.8752366900f, 0.8751439452f, + 0.8750510812f, 0.8749582767f, 0.8748654127f, 0.8747724891f, 0.8746795654f, + 0.8745866418f, 0.8744936585f, 0.8744006753f, 0.8743075728f, 0.8742145300f, + 0.8741214275f, 0.8740282059f, 0.8739350438f, 0.8738418221f, 0.8737486005f, + 0.8736553788f, 0.8735619783f, 0.8734686375f, 0.8733752966f, 0.8732818365f, + 0.8731884360f, 0.8730949759f, 0.8730015159f, 0.8729079962f, 0.8728143573f, + 0.8727207780f, 0.8726271391f, 0.8725334406f, 0.8724397421f, 0.8723460436f, + 0.8722522855f, 0.8721585274f, 0.8720646501f, 0.8719708323f, 0.8718769550f, + 0.8717829585f, 0.8716890216f, 0.8715950847f, 0.8715010881f, 0.8714070320f, + 0.8713129163f, 0.8712188005f, 0.8711246848f, 0.8710304499f, 0.8709362745f, + 0.8708420396f, 0.8707478046f, 0.8706535101f, 0.8705590963f, 0.8704647422f, + 0.8703703880f, 0.8702759147f, 0.8701814413f, 0.8700869679f, 0.8699924350f, + 0.8698979020f, 0.8698033094f, 0.8697086573f, 0.8696140051f, 0.8695192933f, + 0.8694245815f, 0.8693298697f, 0.8692350984f, 0.8691402674f, 0.8690453768f, + 0.8689505458f, 0.8688555956f, 0.8687606454f, 0.8686656952f, 0.8685706854f, + 0.8684756756f, 0.8683806062f, 0.8682854772f, 0.8681903481f, 0.8680951595f, + 0.8679999113f, 0.8679047227f, 0.8678094745f, 0.8677142262f, 0.8676189184f, + 0.8675235510f, 0.8674281240f, 0.8673326969f, 0.8672372699f, 0.8671417236f, + 0.8670462370f, 0.8669506907f, 0.8668551445f, 0.8667595387f, 0.8666638136f, + 0.8665682077f, 0.8664724827f, 0.8663766980f, 0.8662809134f, 0.8661851287f, + 0.8660893440f, 0.8659934998f, 0.8658975363f, 0.8658016324f, 0.8657056689f, + 0.8656096458f, 0.8655136228f, 0.8654175401f, 0.8653214574f, 0.8652253747f, + 0.8651291728f, 0.8650330305f, 0.8649367690f, 0.8648405075f, 0.8647442460f, + 0.8646479249f, 0.8645516038f, 0.8644552231f, 0.8643587828f, 0.8642624021f, + 0.8641659021f, 0.8640693426f, 0.8639728427f, 0.8638762832f, 0.8637797236f, + 0.8636831045f, 0.8635863662f, 0.8634896874f, 0.8633929491f, 0.8632961512f, + 0.8631994128f, 0.8631026149f, 0.8630057573f, 0.8629088998f, 0.8628119230f, + 0.8627150059f, 0.8626180291f, 0.8625209928f, 0.8624239564f, 0.8623268604f, + 0.8622297645f, 0.8621326685f, 0.8620354533f, 0.8619382381f, 0.8618410230f, + 0.8617437482f, 0.8616464138f, 0.8615491390f, 0.8614518046f, 0.8613544106f, + 0.8612569571f, 0.8611595035f, 0.8610619903f, 0.8609644771f, 0.8608669043f, + 0.8607693315f, 0.8606717587f, 0.8605741262f, 0.8604763746f, 0.8603786826f, + 0.8602809906f, 0.8601831198f, 0.8600853682f, 0.8599875569f, 0.8598896861f, + 0.8597918153f, 0.8596938252f, 0.8595958948f, 0.8594979048f, 0.8593998551f, + 0.8593018055f, 0.8592036963f, 0.8591055870f, 0.8590074778f, 0.8589092493f, + 0.8588110209f, 0.8587127924f, 0.8586145043f, 0.8585162163f, 0.8584178686f, + 0.8583195210f, 0.8582211137f, 0.8581226468f, 0.8580241799f, 0.8579257131f, + 0.8578271270f, 0.8577286005f, 0.8576300144f, 0.8575313687f, 0.8574327230f, + 0.8573340178f, 0.8572353125f, 0.8571365476f, 0.8570378423f, 0.8569389582f, + 0.8568401337f, 0.8567412496f, 0.8566423655f, 0.8565434217f, 0.8564444184f, + 0.8563454151f, 0.8562464118f, 0.8561472893f, 0.8560482264f, 0.8559491038f, + 0.8558499813f, 0.8557507992f, 0.8556514978f, 0.8555522561f, 0.8554530144f, + 0.8553536534f, 0.8552542925f, 0.8551549315f, 0.8550555706f, 0.8549560905f, + 0.8548566103f, 0.8547570705f, 0.8546575904f, 0.8545579910f, 0.8544583917f, + 0.8543587327f, 0.8542591333f, 0.8541594148f, 0.8540596366f, 0.8539599180f, + 0.8538601398f, 0.8537602425f, 0.8536604047f, 0.8535605669f, 0.8534606695f, + 0.8533607125f, 0.8532606959f, 0.8531607389f, 0.8530606627f, 0.8529605865f, + 0.8528605103f, 0.8527603745f, 0.8526602387f, 0.8525600433f, 0.8524597883f, + 0.8523595333f, 0.8522592187f, 0.8521588445f, 0.8520585299f, 0.8519581556f, + 0.8518577218f, 0.8517572880f, 0.8516567945f, 0.8515563011f, 0.8514557481f, + 0.8513551354f, 0.8512545824f, 0.8511539102f, 0.8510532975f, 0.8509526253f, + 0.8508518338f, 0.8507511020f, 0.8506503105f, 0.8505494595f, 0.8504486084f, + 0.8503477573f, 0.8502468467f, 0.8501458764f, 0.8500448465f, 0.8499438763f, + 0.8498428464f, 0.8497417569f, 0.8496406674f, 0.8495395184f, 0.8494383693f, + 0.8493371606f, 0.8492358923f, 0.8491346240f, 0.8490333557f, 0.8489320278f, + 0.8488306403f, 0.8487293124f, 0.8486279249f, 0.8485264778f, 0.8484249115f, + 0.8483234644f, 0.8482218981f, 0.8481202722f, 0.8480187058f, 0.8479170799f, + 0.8478154540f, 0.8477137685f, 0.8476119637f, 0.8475102186f, 0.8474084735f, + 0.8473066092f, 0.8472047448f, 0.8471028805f, 0.8470009565f, 0.8468990326f, + 0.8467970490f, 0.8466950059f, 0.8465930223f, 0.8464909196f, 0.8463888168f, + 0.8462867141f, 0.8461845517f, 0.8460823298f, 0.8459800482f, 0.8458778262f, + 0.8457755446f, 0.8456732631f, 0.8455708623f, 0.8454685211f, 0.8453661203f, + 0.8452636600f, 0.8451611996f, 0.8450586796f, 0.8449561596f, 0.8448535800f, + 0.8447509408f, 0.8446483016f, 0.8445456624f, 0.8444430232f, 0.8443402648f, + 0.8442375064f, 0.8441346884f, 0.8440319300f, 0.8439289927f, 0.8438261747f, + 0.8437232375f, 0.8436203599f, 0.8435173631f, 0.8434143066f, 0.8433113098f, + 0.8432082534f, 0.8431050777f, 0.8430020213f, 0.8428988457f, 0.8427956700f, + 0.8426924944f, 0.8425891995f, 0.8424859047f, 0.8423826098f, 0.8422792554f, + 0.8421758413f, 0.8420724869f, 0.8419690728f, 0.8418655992f, 0.8417620659f, + 0.8416585326f, 0.8415549994f, 0.8414513469f, 0.8413477540f, 0.8412441015f, + 0.8411404490f, 0.8410367370f, 0.8409329653f, 0.8408291936f, 0.8407253623f, + 0.8406214714f, 0.8405176401f, 0.8404137492f, 0.8403098583f, 0.8402059078f, + 0.8401018381f, 0.8399978280f, 0.8398938179f, 0.8397896886f, 0.8396855593f, + 0.8395814300f, 0.8394772410f, 0.8393730521f, 0.8392688036f, 0.8391644955f, + 0.8390602469f, 0.8389558792f, 0.8388515115f, 0.8387471437f, 0.8386427164f, + 0.8385382891f, 0.8384337425f, 0.8383292556f, 0.8382247090f, 0.8381201029f, + 0.8380154967f, 0.8379108310f, 0.8378062248f, 0.8377014995f, 0.8375967145f, + 0.8374919891f, 0.8373872042f, 0.8372823000f, 0.8371774554f, 0.8370726109f, + 0.8369677067f, 0.8368627429f, 0.8367577195f, 0.8366527557f, 0.8365477324f, + 0.8364425898f, 0.8363375068f, 0.8362324238f, 0.8361272812f, 0.8360220790f, + 0.8359168172f, 0.8358115554f, 0.8357062936f, 0.8356009126f, 0.8354955912f, + 0.8353902102f, 0.8352848291f, 0.8351793885f, 0.8350738883f, 0.8349683881f, + 0.8348628879f, 0.8347572684f, 0.8346517086f, 0.8345460892f, 0.8344404101f, + 0.8343347907f, 0.8342290521f, 0.8341232538f, 0.8340175152f, 0.8339117169f, + 0.8338057995f, 0.8336999416f, 0.8335940838f, 0.8334881663f, 0.8333822489f, + 0.8332761526f, 0.8331701756f, 0.8330641389f, 0.8329579830f, 0.8328518867f, + 0.8327457905f, 0.8326395750f, 0.8325334191f, 0.8324271441f, 0.8323208690f, + 0.8322145939f, 0.8321081996f, 0.8320018649f, 0.8318954706f, 0.8317890763f, + 0.8316826224f, 0.8315761089f, 0.8314695954f, 0.8313630819f, 0.8312564492f, + 0.8311498761f, 0.8310432434f, 0.8309366107f, 0.8308299184f, 0.8307231665f, + 0.8306164145f, 0.8305096030f, 0.8304027319f, 0.8302959204f, 0.8301890492f, + 0.8300821781f, 0.8299752474f, 0.8298681974f, 0.8297612071f, 0.8296542168f, + 0.8295471072f, 0.8294399977f, 0.8293328881f, 0.8292257786f, 0.8291186094f, + 0.8290113211f, 0.8289040923f, 0.8287968636f, 0.8286895156f, 0.8285821676f, + 0.8284748197f, 0.8283674121f, 0.8282600045f, 0.8281525373f, 0.8280450106f, + 0.8279375434f, 0.8278299570f, 0.8277223706f, 0.8276147842f, 0.8275071383f, + 0.8273994923f, 0.8272917271f, 0.8271840215f, 0.8270762563f, 0.8269684315f, + 0.8268606067f, 0.8267527819f, 0.8266448975f, 0.8265370131f, 0.8264290094f, + 0.8263210654f, 0.8262130618f, 0.8261049986f, 0.8259969354f, 0.8258888125f, + 0.8257807493f, 0.8256725669f, 0.8255643249f, 0.8254561424f, 0.8253479004f, + 0.8252395988f, 0.8251312971f, 0.8250229359f, 0.8249145746f, 0.8248062134f, + 0.8246977329f, 0.8245892525f, 0.8244807720f, 0.8243722320f, 0.8242636919f, + 0.8241551518f, 0.8240465522f, 0.8239378929f, 0.8238291740f, 0.8237205148f, + 0.8236117363f, 0.8235029578f, 0.8233941793f, 0.8232853413f, 0.8231765032f, + 0.8230676651f, 0.8229587078f, 0.8228497505f, 0.8227407932f, 0.8226317167f, + 0.8225226998f, 0.8224136829f, 0.8223046064f, 0.8221954703f, 0.8220863342f, + 0.8219770789f, 0.8218678832f, 0.8217586875f, 0.8216493130f, 0.8215400577f, + 0.8214307427f, 0.8213213682f, 0.8212119937f, 0.8211025000f, 0.8209930658f, + 0.8208835721f, 0.8207740188f, 0.8206644654f, 0.8205549121f, 0.8204452991f, + 0.8203356862f, 0.8202259541f, 0.8201162815f, 0.8200065494f, 0.8198967576f, + 0.8197869658f, 0.8196771741f, 0.8195673227f, 0.8194574714f, 0.8193475008f, + 0.8192375898f, 0.8191276193f, 0.8190175891f, 0.8189075589f, 0.8187974691f, + 0.8186874390f, 0.8185772896f, 0.8184671402f, 0.8183569312f, 0.8182467222f, + 0.8181364536f, 0.8180261850f, 0.8179159164f, 0.8178055882f, 0.8176952004f, + 0.8175848126f, 0.8174743652f, 0.8173639774f, 0.8172534108f, 0.8171429038f, + 0.8170323968f, 0.8169218302f, 0.8168112040f, 0.8167005181f, 0.8165898919f, + 0.8164792061f, 0.8163684607f, 0.8162577152f, 0.8161469102f, 0.8160361052f, + 0.8159253001f, 0.8158143759f, 0.8157035112f, 0.8155925870f, 0.8154815435f, + 0.8153705597f, 0.8152595758f, 0.8151485324f, 0.8150374889f, 0.8149262667f, + 0.8148151636f, 0.8147040009f, 0.8145927787f, 0.8144815564f, 0.8143702745f, + 0.8142589927f, 0.8141477108f, 0.8140363097f, 0.8139249086f, 0.8138135076f, + 0.8137020469f, 0.8135905862f, 0.8134790659f, 0.8133676052f, 0.8132560253f, + 0.8131443858f, 0.8130327463f, 0.8129211068f, 0.8128094077f, 0.8126977086f, + 0.8125859499f, 0.8124741912f, 0.8123624325f, 0.8122505546f, 0.8121386766f, + 0.8120267987f, 0.8119148612f, 0.8118029237f, 0.8116909266f, 0.8115789294f, + 0.8114669323f, 0.8113548160f, 0.8112426996f, 0.8111305833f, 0.8110184073f, + 0.8109062314f, 0.8107939959f, 0.8106817603f, 0.8105695248f, 0.8104571700f, + 0.8103448153f, 0.8102325201f, 0.8101201057f, 0.8100076318f, 0.8098952174f, + 0.8097827435f, 0.8096702099f, 0.8095576763f, 0.8094450235f, 0.8093324304f, + 0.8092198372f, 0.8091071248f, 0.8089944124f, 0.8088817000f, 0.8087689877f, + 0.8086562157f, 0.8085433245f, 0.8084304929f, 0.8083176613f, 0.8082047105f, + 0.8080917597f, 0.8079788089f, 0.8078658581f, 0.8077528477f, 0.8076397181f, + 0.8075267076f, 0.8074135780f, 0.8073003888f, 0.8071871996f, 0.8070740700f, + 0.8069608212f, 0.8068475723f, 0.8067342639f, 0.8066209555f, 0.8065075874f, + 0.8063941598f, 0.8062807918f, 0.8061673641f, 0.8060538769f, 0.8059403896f, + 0.8058268428f, 0.8057132959f, 0.8055997491f, 0.8054860830f, 0.8053724170f, + 0.8052587509f, 0.8051450849f, 0.8050313592f, 0.8049175143f, 0.8048037887f, + 0.8046899438f, 0.8045760393f, 0.8044621944f, 0.8043482900f, 0.8042343855f, + 0.8041204214f, 0.8040063381f, 0.8038923144f, 0.8037782907f, 0.8036641479f, + 0.8035500646f, 0.8034359217f, 0.8033217192f, 0.8032075167f, 0.8030932546f, + 0.8029789925f, 0.8028647304f, 0.8027503490f, 0.8026360273f, 0.8025216460f, + 0.8024072647f, 0.8022928238f, 0.8021782637f, 0.8020638227f, 0.8019492626f, + 0.8018347025f, 0.8017200828f, 0.8016054630f, 0.8014908433f, 0.8013761640f, + 0.8012614250f, 0.8011466861f, 0.8010319471f, 0.8009170890f, 0.8008022904f, + 0.8006874323f, 0.8005725741f, 0.8004576564f, 0.8003426790f, 0.8002277017f, + 0.8001127243f, 0.7999976277f, 0.7998825908f, 0.7997675538f, 0.7996523976f, + 0.7995373011f, 0.7994220257f, 0.7993068695f, 0.7991916537f, 0.7990763187f, + 0.7989610434f, 0.7988457084f, 0.7987303734f, 0.7986149788f, 0.7984995246f, + 0.7983840704f, 0.7982686758f, 0.7981531024f, 0.7980375886f, 0.7979220152f, + 0.7978064418f, 0.7976908684f, 0.7975752354f, 0.7974594831f, 0.7973437905f, + 0.7972280979f, 0.7971122861f, 0.7969964743f, 0.7968806624f, 0.7967648506f, + 0.7966489792f, 0.7965329885f, 0.7964170575f, 0.7963011265f, 0.7961850762f, + 0.7960690260f, 0.7959529757f, 0.7958369255f, 0.7957208157f, 0.7956045866f, + 0.7954884768f, 0.7953722477f, 0.7952559590f, 0.7951397300f, 0.7950234413f, + 0.7949071527f, 0.7947908044f, 0.7946743965f, 0.7945579886f, 0.7944415212f, + 0.7943250537f, 0.7942085266f, 0.7940920591f, 0.7939754725f, 0.7938588858f, + 0.7937422395f, 0.7936255932f, 0.7935089469f, 0.7933922410f, 0.7932754755f, + 0.7931587696f, 0.7930419445f, 0.7929251790f, 0.7928082347f, 0.7926914096f, + 0.7925745249f, 0.7924575210f, 0.7923405766f, 0.7922235727f, 0.7921065688f, + 0.7919895649f, 0.7918724418f, 0.7917553186f, 0.7916381955f, 0.7915209532f, + 0.7914037704f, 0.7912865877f, 0.7911693454f, 0.7910520434f, 0.7909346819f, + 0.7908173800f, 0.7907000184f, 0.7905825377f, 0.7904651165f, 0.7903476954f, + 0.7902302146f, 0.7901127338f, 0.7899951339f, 0.7898775339f, 0.7897599936f, + 0.7896422744f, 0.7895246148f, 0.7894069552f, 0.7892892361f, 0.7891715169f, + 0.7890536785f, 0.7889358997f, 0.7888180614f, 0.7887001634f, 0.7885822654f, + 0.7884643674f, 0.7883464098f, 0.7882284522f, 0.7881103754f, 0.7879923582f, + 0.7878743410f, 0.7877562046f, 0.7876380682f, 0.7875199318f, 0.7874017358f, + 0.7872835398f, 0.7871652246f, 0.7870469689f, 0.7869287133f, 0.7868103385f, + 0.7866919637f, 0.7865735888f, 0.7864552140f, 0.7863367796f, 0.7862182260f, + 0.7860997915f, 0.7859812379f, 0.7858626246f, 0.7857440710f, 0.7856254578f, + 0.7855068445f, 0.7853881717f, 0.7852693796f, 0.7851507068f, 0.7850319147f, + 0.7849130630f, 0.7847942710f, 0.7846754193f, 0.7845566273f, 0.7844377160f, + 0.7843188047f, 0.7841997743f, 0.7840808034f, 0.7839617729f, 0.7838426828f, + 0.7837235928f, 0.7836045027f, 0.7834854126f, 0.7833662629f, 0.7832469940f, + 0.7831277847f, 0.7830085754f, 0.7828892469f, 0.7827699184f, 0.7826505899f, + 0.7825312614f, 0.7824118733f, 0.7822923660f, 0.7821729183f, 0.7820534706f, + 0.7819339037f, 0.7818143964f, 0.7816948295f, 0.7815752625f, 0.7814556360f, + 0.7813359499f, 0.7812162638f, 0.7810965776f, 0.7809767723f, 0.7808570266f, + 0.7807372212f, 0.7806174159f, 0.7804975510f, 0.7803776264f, 0.7802577615f, + 0.7801377773f, 0.7800177932f, 0.7798978090f, 0.7797777653f, 0.7796577215f, + 0.7795376778f, 0.7794175148f, 0.7792973518f, 0.7791771889f, 0.7790569663f, + 0.7789367437f, 0.7788165212f, 0.7786962390f, 0.7785759568f, 0.7784555554f, + 0.7783351541f, 0.7782148123f, 0.7780942917f, 0.7779738903f, 0.7778533697f, + 0.7777329087f, 0.7776123285f, 0.7774917483f, 0.7773711681f, 0.7772505283f, + 0.7771298289f, 0.7770091295f, 0.7768884301f, 0.7767677307f, 0.7766469717f, + 0.7765260935f, 0.7764052749f, 0.7762844563f, 0.7761635184f, 0.7760425806f, + 0.7759217024f, 0.7758007050f, 0.7756797671f, 0.7755586505f, 0.7754375935f, + 0.7753165364f, 0.7751953602f, 0.7750742435f, 0.7749530673f, 0.7748318911f, + 0.7747106552f, 0.7745893598f, 0.7744681239f, 0.7743468285f, 0.7742254138f, + 0.7741040587f, 0.7739826441f, 0.7738612294f, 0.7737398148f, 0.7736182809f, + 0.7734967470f, 0.7733752728f, 0.7732536197f, 0.7731320262f, 0.7730104327f, + 0.7728887796f, 0.7727671266f, 0.7726453543f, 0.7725236416f, 0.7724018693f, + 0.7722800374f, 0.7721582055f, 0.7720363736f, 0.7719144821f, 0.7717925906f, + 0.7716705799f, 0.7715486288f, 0.7714266777f, 0.7713046670f, 0.7711825967f, + 0.7710605264f, 0.7709383965f, 0.7708162665f, 0.7706941366f, 0.7705718875f, + 0.7704496980f, 0.7703274488f, 0.7702051401f, 0.7700828314f, 0.7699605227f, + 0.7698381543f, 0.7697157860f, 0.7695932984f, 0.7694708705f, 0.7693483829f, + 0.7692258358f, 0.7691033483f, 0.7689807415f, 0.7688581944f, 0.7687355876f, + 0.7686128616f, 0.7684901953f, 0.7683675289f, 0.7682447433f, 0.7681220174f, + 0.7679992318f, 0.7678764462f, 0.7677536011f, 0.7676306963f, 0.7675077915f, + 0.7673848867f, 0.7672618628f, 0.7671388984f, 0.7670158744f, 0.7668928504f, + 0.7667698264f, 0.7666466236f, 0.7665235400f, 0.7664003968f, 0.7662771940f, + 0.7661539912f, 0.7660307288f, 0.7659074664f, 0.7657842040f, 0.7656608224f, + 0.7655375004f, 0.7654141188f, 0.7652906775f, 0.7651672363f, 0.7650437951f, + 0.7649202943f, 0.7647967935f, 0.7646732330f, 0.7645496130f, 0.7644260526f, + 0.7643023729f, 0.7641786933f, 0.7640550137f, 0.7639313340f, 0.7638075948f, + 0.7636837959f, 0.7635599971f, 0.7634361386f, 0.7633122802f, 0.7631883621f, + 0.7630645037f, 0.7629405260f, 0.7628166080f, 0.7626925707f, 0.7625685334f, + 0.7624444962f, 0.7623203397f, 0.7621962428f, 0.7620721459f, 0.7619479895f, + 0.7618238330f, 0.7616995573f, 0.7615752816f, 0.7614510059f, 0.7613266706f, + 0.7612023354f, 0.7610780001f, 0.7609536052f, 0.7608292103f, 0.7607046962f, + 0.7605802417f, 0.7604557872f, 0.7603311539f, 0.7602066398f, 0.7600820661f, + 0.7599574327f, 0.7598328590f, 0.7597081065f, 0.7595834136f, 0.7594587207f, + 0.7593339086f, 0.7592091560f, 0.7590843439f, 0.7589595318f, 0.7588346601f, + 0.7587097287f, 0.7585847974f, 0.7584598660f, 0.7583348751f, 0.7582098842f, + 0.7580848336f, 0.7579597831f, 0.7578347325f, 0.7577095628f, 0.7575844526f, + 0.7574592829f, 0.7573341131f, 0.7572088242f, 0.7570835948f, 0.7569583058f, + 0.7568330169f, 0.7567076683f, 0.7565822601f, 0.7564569116f, 0.7563314438f, + 0.7562059760f, 0.7560805082f, 0.7559549809f, 0.7558295131f, 0.7557039261f, + 0.7555782795f, 0.7554526925f, 0.7553270459f, 0.7552013397f, 0.7550756931f, + 0.7549499273f, 0.7548241615f, 0.7546983957f, 0.7545725703f, 0.7544467449f, + 0.7543208599f, 0.7541949153f, 0.7540690303f, 0.7539430857f, 0.7538171411f, + 0.7536911368f, 0.7535650730f, 0.7534390092f, 0.7533129454f, 0.7531867623f, + 0.7530606389f, 0.7529344559f, 0.7528082728f, 0.7526820898f, 0.7525557280f, + 0.7524294853f, 0.7523031831f, 0.7521768212f, 0.7520504594f, 0.7519240379f, + 0.7517976761f, 0.7516711950f, 0.7515447140f, 0.7514182329f, 0.7512916923f, + 0.7511650920f, 0.7510385513f, 0.7509118915f, 0.7507852912f, 0.7506586313f, + 0.7505319118f, 0.7504051924f, 0.7502784133f, 0.7501516342f, 0.7500247955f, + 0.7498979568f, 0.7497711182f, 0.7496442795f, 0.7495172620f, 0.7493903637f, + 0.7492634058f, 0.7491363287f, 0.7490093112f, 0.7488822937f, 0.7487552166f, + 0.7486281395f, 0.7485009432f, 0.7483738065f, 0.7482466102f, 0.7481193542f, + 0.7479920983f, 0.7478648424f, 0.7477375269f, 0.7476102114f, 0.7474827766f, + 0.7473554611f, 0.7472280264f, 0.7471005321f, 0.7469730973f, 0.7468456030f, + 0.7467181087f, 0.7465905547f, 0.7464629412f, 0.7463353276f, 0.7462077141f, + 0.7460800409f, 0.7459523082f, 0.7458246350f, 0.7456969023f, 0.7455691695f, + 0.7454413176f, 0.7453134656f, 0.7451856136f, 0.7450577021f, 0.7449297905f, + 0.7448019385f, 0.7446739674f, 0.7445459962f, 0.7444179058f, 0.7442898750f, + 0.7441618443f, 0.7440336943f, 0.7439056039f, 0.7437774539f, 0.7436492443f, + 0.7435210943f, 0.7433928847f, 0.7432645559f, 0.7431362867f, 0.7430079579f, + 0.7428795695f, 0.7427512407f, 0.7426228523f, 0.7424944043f, 0.7423659563f, + 0.7422374487f, 0.7421089411f, 0.7419804335f, 0.7418518066f, 0.7417232394f, + 0.7415946126f, 0.7414659858f, 0.7413373590f, 0.7412086129f, 0.7410798669f, + 0.7409511805f, 0.7408223152f, 0.7406935096f, 0.7405647039f, 0.7404358387f, + 0.7403069735f, 0.7401779890f, 0.7400490642f, 0.7399201393f, 0.7397910357f, + 0.7396620512f, 0.7395330071f, 0.7394039631f, 0.7392748594f, 0.7391456366f, + 0.7390164733f, 0.7388873100f, 0.7387580872f, 0.7386288643f, 0.7384995818f, + 0.7383702993f, 0.7382410169f, 0.7381116152f, 0.7379822135f, 0.7378528118f, + 0.7377233505f, 0.7375938892f, 0.7374644279f, 0.7373349071f, 0.7372053862f, + 0.7370758057f, 0.7369462252f, 0.7368165851f, 0.7366868854f, 0.7365571856f, + 0.7364275455f, 0.7362977862f, 0.7361680269f, 0.7360382080f, 0.7359083891f, + 0.7357785702f, 0.7356486917f, 0.7355188131f, 0.7353888750f, 0.7352589369f, + 0.7351289988f, 0.7349989414f, 0.7348689437f, 0.7347388864f, 0.7346087694f, + 0.7344786525f, 0.7343485355f, 0.7342183590f, 0.7340881824f, 0.7339579463f, + 0.7338277102f, 0.7336974144f, 0.7335670590f, 0.7334367633f, 0.7333064079f, + 0.7331760526f, 0.7330456376f, 0.7329151630f, 0.7327847481f, 0.7326542735f, + 0.7325236797f, 0.7323932052f, 0.7322626114f, 0.7321320176f, 0.7320014238f, + 0.7318707108f, 0.7317400575f, 0.7316093445f, 0.7314785719f, 0.7313478589f, + 0.7312170863f, 0.7310862541f, 0.7309554815f, 0.7308245301f, 0.7306936383f, + 0.7305627465f, 0.7304317355f, 0.7303007841f, 0.7301698327f, 0.7300387621f, + 0.7299077511f, 0.7297766209f, 0.7296455503f, 0.7295144200f, 0.7293832302f, + 0.7292520404f, 0.7291208506f, 0.7289896011f, 0.7288583517f, 0.7287271023f, + 0.7285957336f, 0.7284643650f, 0.7283330560f, 0.7282015681f, 0.7280701399f, + 0.7279387116f, 0.7278072834f, 0.7276757360f, 0.7275441885f, 0.7274126410f, + 0.7272810936f, 0.7271493673f, 0.7270177603f, 0.7268860936f, 0.7267544270f, + 0.7266227007f, 0.7264909148f, 0.7263591290f, 0.7262274027f, 0.7260954976f, + 0.7259636521f, 0.7258318067f, 0.7256998420f, 0.7255679369f, 0.7254359126f, + 0.7253040075f, 0.7251719236f, 0.7250398397f, 0.7249078155f, 0.7247757316f, + 0.7246436477f, 0.7245115042f, 0.7243792415f, 0.7242470980f, 0.7241148353f, + 0.7239825726f, 0.7238503098f, 0.7237179875f, 0.7235856652f, 0.7234532833f, + 0.7233209014f, 0.7231884599f, 0.7230560184f, 0.7229235172f, 0.7227910757f, + 0.7226585150f, 0.7225260139f, 0.7223934531f, 0.7222607732f, 0.7221281528f, + 0.7219955325f, 0.7218627930f, 0.7217301130f, 0.7215973735f, 0.7214646339f, + 0.7213318348f, 0.7211990356f, 0.7210661769f, 0.7209333181f, 0.7208003998f, + 0.7206674814f, 0.7205345631f, 0.7204015851f, 0.7202686071f, 0.7201355100f, + 0.7200024724f, 0.7198694348f, 0.7197362781f, 0.7196031809f, 0.7194700241f, + 0.7193368077f, 0.7192036510f, 0.7190703750f, 0.7189370990f, 0.7188038230f, + 0.7186704874f, 0.7185370922f, 0.7184037566f, 0.7182703614f, 0.7181369662f, + 0.7180035114f, 0.7178699970f, 0.7177365422f, 0.7176029682f, 0.7174694538f, + 0.7173358202f, 0.7172022462f, 0.7170686126f, 0.7169349194f, 0.7168012261f, + 0.7166675329f, 0.7165337801f, 0.7164000273f, 0.7162662148f, 0.7161324024f, + 0.7159985900f, 0.7158646584f, 0.7157307863f, 0.7155968547f, 0.7154628634f, + 0.7153289318f, 0.7151949406f, 0.7150608897f, 0.7149268389f, 0.7147927284f, + 0.7146586180f, 0.7145245671f, 0.7143903971f, 0.7142561674f, 0.7141219974f, + 0.7139877677f, 0.7138534784f, 0.7137191892f, 0.7135848403f, 0.7134505510f, + 0.7133161426f, 0.7131817341f, 0.7130473256f, 0.7129128575f, 0.7127784491f, + 0.7126439214f, 0.7125093341f, 0.7123748064f, 0.7122402191f, 0.7121055722f, + 0.7119709849f, 0.7118363380f, 0.7117016912f, 0.7115669847f, 0.7114322186f, + 0.7112973928f, 0.7111626863f, 0.7110278010f, 0.7108929753f, 0.7107580900f, + 0.7106232643f, 0.7104883194f, 0.7103533149f, 0.7102183700f, 0.7100833654f, + 0.7099483013f, 0.7098132968f, 0.7096782327f, 0.7095431089f, 0.7094079852f, + 0.7092728019f, 0.7091376185f, 0.7090024352f, 0.7088671923f, 0.7087319493f, + 0.7085966468f, 0.7084613442f, 0.7083259821f, 0.7081906199f, 0.7080552578f, + 0.7079197764f, 0.7077843547f, 0.7076488733f, 0.7075133920f, 0.7073779106f, + 0.7072423697f, 0.7071067691f, 0.7069711685f, 0.7068355083f, 0.7066999078f, + 0.7065641880f, 0.7064285278f, 0.7062927485f, 0.7061570287f, 0.7060212493f, + 0.7058854103f, 0.7057496309f, 0.7056137323f, 0.7054778337f, 0.7053419352f, + 0.7052060366f, 0.7050700188f, 0.7049340606f, 0.7047980428f, 0.7046619654f, + 0.7045259476f, 0.7043898106f, 0.7042537332f, 0.7041175961f, 0.7039813995f, + 0.7038452029f, 0.7037090063f, 0.7035727501f, 0.7034364939f, 0.7033001781f, + 0.7031638622f, 0.7030274868f, 0.7028911114f, 0.7027547359f, 0.7026183009f, + 0.7024818063f, 0.7023453712f, 0.7022088170f, 0.7020723224f, 0.7019357681f, + 0.7017991543f, 0.7016625404f, 0.7015259266f, 0.7013892531f, 0.7012525797f, + 0.7011158466f, 0.7009791136f, 0.7008423805f, 0.7007055879f, 0.7005687356f, + 0.7004319429f, 0.7002950311f, 0.7001581788f, 0.7000212669f, 0.6998842955f, + 0.6997473240f, 0.6996103525f, 0.6994733810f, 0.6993362904f, 0.6991991997f, + 0.6990621090f, 0.6989250183f, 0.6987878680f, 0.6986507177f, 0.6985135078f, + 0.6983762383f, 0.6982389688f, 0.6981016994f, 0.6979644299f, 0.6978271008f, + 0.6976897120f, 0.6975523233f, 0.6974149346f, 0.6972774863f, 0.6971400380f, + 0.6970025897f, 0.6968650818f, 0.6967275143f, 0.6965899467f, 0.6964523792f, + 0.6963147521f, 0.6961771250f, 0.6960394382f, 0.6959017515f, 0.6957640648f, + 0.6956263185f, 0.6954885721f, 0.6953507662f, 0.6952129602f, 0.6950750947f, + 0.6949372292f, 0.6947993636f, 0.6946614385f, 0.6945234537f, 0.6943855286f, + 0.6942474842f, 0.6941094995f, 0.6939714551f, 0.6938333511f, 0.6936953068f, + 0.6935571432f, 0.6934189796f, 0.6932808161f, 0.6931426525f, 0.6930044293f, + 0.6928661466f, 0.6927278638f, 0.6925895810f, 0.6924512386f, 0.6923128963f, + 0.6921745539f, 0.6920361519f, 0.6918976903f, 0.6917592287f, 0.6916207671f, + 0.6914822459f, 0.6913437247f, 0.6912051439f, 0.6910665631f, 0.6909279823f, + 0.6907893419f, 0.6906507015f, 0.6905120015f, 0.6903733015f, 0.6902345419f, + 0.6900957823f, 0.6899570227f, 0.6898182034f, 0.6896793842f, 0.6895405054f, + 0.6894016266f, 0.6892627478f, 0.6891238093f, 0.6889848113f, 0.6888458133f, + 0.6887068152f, 0.6885678172f, 0.6884287000f, 0.6882896423f, 0.6881505251f, + 0.6880114079f, 0.6878722310f, 0.6877330542f, 0.6875938177f, 0.6874545813f, + 0.6873152852f, 0.6871759892f, 0.6870366931f, 0.6868973374f, 0.6867579818f, + 0.6866186261f, 0.6864792109f, 0.6863397360f, 0.6862002611f, 0.6860607862f, + 0.6859212518f, 0.6857817173f, 0.6856421232f, 0.6855025291f, 0.6853629351f, + 0.6852232814f, 0.6850836277f, 0.6849439144f, 0.6848042011f, 0.6846644878f, + 0.6845247149f, 0.6843849421f, 0.6842451096f, 0.6841052771f, 0.6839654446f, + 0.6838254929f, 0.6836856008f, 0.6835456491f, 0.6834056973f, 0.6832656860f, + 0.6831256747f, 0.6829856038f, 0.6828455329f, 0.6827054620f, 0.6825653315f, + 0.6824252009f, 0.6822850108f, 0.6821448207f, 0.6820045710f, 0.6818643212f, + 0.6817240715f, 0.6815837622f, 0.6814434528f, 0.6813030839f, 0.6811627150f, + 0.6810223460f, 0.6808819175f, 0.6807414293f, 0.6806010008f, 0.6804605126f, + 0.6803199649f, 0.6801794171f, 0.6800388694f, 0.6798982620f, 0.6797575951f, + 0.6796169877f, 0.6794763207f, 0.6793355942f, 0.6791948676f, 0.6790541410f, + 0.6789133549f, 0.6787725687f, 0.6786317825f, 0.6784908772f, 0.6783500314f, + 0.6782091260f, 0.6780682206f, 0.6779272556f, 0.6777862906f, 0.6776453257f, + 0.6775043011f, 0.6773632169f, 0.6772221327f, 0.6770810485f, 0.6769399643f, + 0.6767988205f, 0.6766576171f, 0.6765164137f, 0.6763752103f, 0.6762339473f, + 0.6760926843f, 0.6759513617f, 0.6758100986f, 0.6756687164f, 0.6755273342f, + 0.6753859520f, 0.6752445698f, 0.6751030684f, 0.6749616265f, 0.6748201251f, + 0.6746786237f, 0.6745370626f, 0.6743955016f, 0.6742538810f, 0.6741122603f, + 0.6739706397f, 0.6738289595f, 0.6736872792f, 0.6735455990f, 0.6734037995f, + 0.6732620597f, 0.6731202602f, 0.6729784608f, 0.6728366017f, 0.6726947427f, + 0.6725528240f, 0.6724109650f, 0.6722689867f, 0.6721270084f, 0.6719850302f, + 0.6718430519f, 0.6717009544f, 0.6715589166f, 0.6714168191f, 0.6712747216f, + 0.6711325645f, 0.6709904075f, 0.6708482504f, 0.6707060337f, 0.6705638170f, + 0.6704215407f, 0.6702792645f, 0.6701369286f, 0.6699945927f, 0.6698522568f, + 0.6697098613f, 0.6695674658f, 0.6694250107f, 0.6692825556f, 0.6691400409f, + 0.6689975262f, 0.6688550115f, 0.6687124968f, 0.6685699224f, 0.6684273481f, + 0.6682847142f, 0.6681420207f, 0.6679993868f, 0.6678566933f, 0.6677139401f, + 0.6675711870f, 0.6674283743f, 0.6672856212f, 0.6671427488f, 0.6669999361f, + 0.6668570638f, 0.6667141318f, 0.6665711999f, 0.6664282680f, 0.6662852764f, + 0.6661422849f, 0.6659992933f, 0.6658562422f, 0.6657131314f, 0.6655700803f, + 0.6654269695f, 0.6652837992f, 0.6651406288f, 0.6649974585f, 0.6648542285f, + 0.6647109985f, 0.6645677090f, 0.6644244194f, 0.6642811298f, 0.6641377807f, + 0.6639943719f, 0.6638510227f, 0.6637076139f, 0.6635641456f, 0.6634206772f, + 0.6632772088f, 0.6631336808f, 0.6629901528f, 0.6628465652f, 0.6627030373f, + 0.6625593901f, 0.6624157429f, 0.6622720957f, 0.6621284485f, 0.6619847417f, + 0.6618409753f, 0.6616972089f, 0.6615534425f, 0.6614096165f, 0.6612658501f, + 0.6611219645f, 0.6609780788f, 0.6608341932f, 0.6606902480f, 0.6605463028f, + 0.6604023576f, 0.6602583528f, 0.6601143479f, 0.6599702835f, 0.6598262191f, + 0.6596820951f, 0.6595379710f, 0.6593938470f, 0.6592496634f, 0.6591054797f, + 0.6589612961f, 0.6588170528f, 0.6586727500f, 0.6585284472f, 0.6583841443f, + 0.6582398415f, 0.6580954790f, 0.6579510570f, 0.6578066349f, 0.6576622128f, + 0.6575177908f, 0.6573733091f, 0.6572287679f, 0.6570842266f, 0.6569396853f, + 0.6567951441f, 0.6566505432f, 0.6565058827f, 0.6563612223f, 0.6562165618f, + 0.6560718417f, 0.6559271216f, 0.6557824016f, 0.6556376219f, 0.6554928422f, + 0.6553480029f, 0.6552031636f, 0.6550582647f, 0.6549133658f, 0.6547684669f, + 0.6546235085f, 0.6544785500f, 0.6543335915f, 0.6541885734f, 0.6540435553f, + 0.6538984776f, 0.6537533998f, 0.6536082625f, 0.6534631252f, 0.6533179879f, + 0.6531727910f, 0.6530275941f, 0.6528823376f, 0.6527371407f, 0.6525918841f, + 0.6524465680f, 0.6523012519f, 0.6521558762f, 0.6520105600f, 0.6518651247f, + 0.6517196894f, 0.6515742540f, 0.6514288187f, 0.6512833238f, 0.6511377692f, + 0.6509922743f, 0.6508466601f, 0.6507011056f, 0.6505554914f, 0.6504098177f, + 0.6502642035f, 0.6501184702f, 0.6499727964f, 0.6498270631f, 0.6496813297f, + 0.6495355368f, 0.6493897438f, 0.6492438912f, 0.6490980387f, 0.6489521861f, + 0.6488062739f, 0.6486603618f, 0.6485143900f, 0.6483684182f, 0.6482224464f, + 0.6480764151f, 0.6479303837f, 0.6477842927f, 0.6476382017f, 0.6474921107f, + 0.6473459601f, 0.6471998096f, 0.6470535994f, 0.6469073892f, 0.6467611790f, + 0.6466149092f, 0.6464686394f, 0.6463223100f, 0.6461759806f, 0.6460296512f, + 0.6458832622f, 0.6457368731f, 0.6455904245f, 0.6454439759f, 0.6452975273f, + 0.6451510191f, 0.6450045109f, 0.6448580027f, 0.6447114348f, 0.6445648074f, + 0.6444181800f, 0.6442715526f, 0.6441249251f, 0.6439782381f, 0.6438315511f, + 0.6436848044f, 0.6435380578f, 0.6433912516f, 0.6432444453f, 0.6430976391f, + 0.6429507732f, 0.6428039074f, 0.6426569819f, 0.6425101161f, 0.6423631310f, + 0.6422162056f, 0.6420691609f, 0.6419221759f, 0.6417751312f, 0.6416280866f, + 0.6414809823f, 0.6413338780f, 0.6411867142f, 0.6410396099f, 0.6408923864f, + 0.6407452226f, 0.6405979991f, 0.6404507160f, 0.6403034329f, 0.6401561499f, + 0.6400088072f, 0.6398614645f, 0.6397141218f, 0.6395667195f, 0.6394193172f, + 0.6392718554f, 0.6391243935f, 0.6389769316f, 0.6388294101f, 0.6386818886f, + 0.6385343075f, 0.6383867264f, 0.6382391453f, 0.6380915046f, 0.6379438639f, + 0.6377961636f, 0.6376485229f, 0.6375007629f, 0.6373530626f, 0.6372052431f, + 0.6370574832f, 0.6369096637f, 0.6367618442f, 0.6366139650f, 0.6364660859f, + 0.6363182068f, 0.6361702681f, 0.6360223293f, 0.6358743310f, 0.6357263327f, + 0.6355783343f, 0.6354302764f, 0.6352822185f, 0.6351341009f, 0.6349859834f, + 0.6348378658f, 0.6346896887f, 0.6345415115f, 0.6343932748f, 0.6342450380f, + 0.6340968013f, 0.6339485049f, 0.6338002086f, 0.6336518526f, 0.6335034966f, + 0.6333551407f, 0.6332067251f, 0.6330583096f, 0.6329098940f, 0.6327614188f, + 0.6326129436f, 0.6324644089f, 0.6323158741f, 0.6321673393f, 0.6320187449f, + 0.6318701506f, 0.6317214966f, 0.6315728426f, 0.6314241886f, 0.6312754750f, + 0.6311267614f, 0.6309779882f, 0.6308292150f, 0.6306804419f, 0.6305316091f, + 0.6303827763f, 0.6302338839f, 0.6300849915f, 0.6299360991f, 0.6297872066f, + 0.6296381950f, 0.6294892430f, 0.6293402314f, 0.6291912198f, 0.6290421486f, + 0.6288930774f, 0.6287440062f, 0.6285948753f, 0.6284457445f, 0.6282966137f, + 0.6281474233f, 0.6279981732f, 0.6278489232f, 0.6276996732f, 0.6275504231f, + 0.6274011135f, 0.6272518039f, 0.6271024346f, 0.6269530654f, 0.6268036962f, + 0.6266542673f, 0.6265048385f, 0.6263553500f, 0.6262058616f, 0.6260563731f, + 0.6259068251f, 0.6257572770f, 0.6256076694f, 0.6254581213f, 0.6253084540f, + 0.6251588464f, 0.6250091791f, 0.6248594522f, 0.6247097254f, 0.6245599985f, + 0.6244102120f, 0.6242604256f, 0.6241106391f, 0.6239607930f, 0.6238109469f, + 0.6236611009f, 0.6235111952f, 0.6233612299f, 0.6232113242f, 0.6230613589f, + 0.6229113340f, 0.6227613688f, 0.6226112843f, 0.6224612594f, 0.6223111749f, + 0.6221610308f, 0.6220109463f, 0.6218608022f, 0.6217105985f, 0.6215603948f, + 0.6214101911f, 0.6212599277f, 0.6211096644f, 0.6209594011f, 0.6208090782f, + 0.6206587553f, 0.6205083728f, 0.6203579903f, 0.6202076077f, 0.6200571656f, + 0.6199067831f, 0.6197562814f, 0.6196057796f, 0.6194552779f, 0.6193047166f, + 0.6191541553f, 0.6190035939f, 0.6188529730f, 0.6187023520f, 0.6185517311f, + 0.6184010506f, 0.6182503104f, 0.6180996299f, 0.6179488897f, 0.6177980900f, + 0.6176472902f, 0.6174964905f, 0.6173456311f, 0.6171947718f, 0.6170439124f, + 0.6168929935f, 0.6167420745f, 0.6165911555f, 0.6164401770f, 0.6162891984f, + 0.6161381602f, 0.6159871221f, 0.6158360243f, 0.6156849861f, 0.6155338883f, + 0.6153827310f, 0.6152315736f, 0.6150804162f, 0.6149291992f, 0.6147779822f, + 0.6146267653f, 0.6144754887f, 0.6143242121f, 0.6141728759f, 0.6140215397f, + 0.6138702035f, 0.6137188077f, 0.6135674119f, 0.6134159565f, 0.6132645607f, + 0.6131130457f, 0.6129615903f, 0.6128100753f, 0.6126585007f, 0.6125069857f, + 0.6123554111f, 0.6122037768f, 0.6120521426f, 0.6119005084f, 0.6117488146f, + 0.6115971208f, 0.6114454269f, 0.6112936735f, 0.6111419201f, 0.6109901667f, + 0.6108383536f, 0.6106864810f, 0.6105346680f, 0.6103827953f, 0.6102308631f, + 0.6100789905f, 0.6099269986f, 0.6097750664f, 0.6096230745f, 0.6094710827f, + 0.6093190312f, 0.6091669798f, 0.6090149283f, 0.6088628173f, 0.6087107062f, + 0.6085585356f, 0.6084063649f, 0.6082541943f, 0.6081019640f, 0.6079497337f, + 0.6077975035f, 0.6076452136f, 0.6074929237f, 0.6073405743f, 0.6071882844f, + 0.6070358753f, 0.6068835258f, 0.6067311168f, 0.6065786481f, 0.6064261794f, + 0.6062737107f, 0.6061212420f, 0.6059687138f, 0.6058161855f, 0.6056635976f, + 0.6055110097f, 0.6053583622f, 0.6052057743f, 0.6050531268f, 0.6049004197f, + 0.6047477126f, 0.6045950055f, 0.6044422388f, 0.6042894721f, 0.6041367054f, + 0.6039838791f, 0.6038310528f, 0.6036782265f, 0.6035253406f, 0.6033723950f, + 0.6032195091f, 0.6030666232f, 0.6029136181f, 0.6027606726f, 0.6026076078f, + 0.6024546027f, 0.6023015380f, 0.6021484733f, 0.6019953489f, 0.6018422246f, + 0.6016891003f, 0.6015359163f, 0.6013827324f, 0.6012295485f, 0.6010763049f, + 0.6009230614f, 0.6007697582f, 0.6006164551f, 0.6004631519f, 0.6003097892f, + 0.6001564264f, 0.6000030637f, 0.5998496413f, 0.5996962190f, 0.5995427370f, + 0.5993893147f, 0.5992357731f, 0.5990822911f, 0.5989287496f, 0.5987751484f, + 0.5986216068f, 0.5984679461f, 0.5983143449f, 0.5981606841f, 0.5980070233f, + 0.5978533030f, 0.5976995826f, 0.5975458622f, 0.5973920822f, 0.5972383022f, + 0.5970845222f, 0.5969306827f, 0.5967768431f, 0.5966229439f, 0.5964691043f, + 0.5963151455f, 0.5961612463f, 0.5960072875f, 0.5958532691f, 0.5956993103f, + 0.5955452323f, 0.5953912139f, 0.5952371359f, 0.5950830579f, 0.5949289203f, + 0.5947747827f, 0.5946206450f, 0.5944664478f, 0.5943122506f, 0.5941580534f, + 0.5940037966f, 0.5938495398f, 0.5936952829f, 0.5935409665f, 0.5933866501f, + 0.5932322741f, 0.5930778980f, 0.5929235220f, 0.5927690864f, 0.5926146507f, + 0.5924601555f, 0.5923057199f, 0.5921511650f, 0.5919966698f, 0.5918421149f, + 0.5916875601f, 0.5915329456f, 0.5913783312f, 0.5912237167f, 0.5910690427f, + 0.5909143686f, 0.5907596946f, 0.5906049609f, 0.5904502273f, 0.5902954340f, + 0.5901406407f, 0.5899858475f, 0.5898309946f, 0.5896761417f, 0.5895212889f, + 0.5893663764f, 0.5892114639f, 0.5890565515f, 0.5889015794f, 0.5887466073f, + 0.5885915756f, 0.5884365439f, 0.5882815123f, 0.5881264210f, 0.5879713297f, + 0.5878162384f, 0.5876610875f, 0.5875059366f, 0.5873507857f, 0.5871955752f, + 0.5870403647f, 0.5868850946f, 0.5867298245f, 0.5865745544f, 0.5864192247f, + 0.5862638950f, 0.5861085653f, 0.5859532356f, 0.5857978463f, 0.5856424570f, + 0.5854870081f, 0.5853315592f, 0.5851760507f, 0.5850205421f, 0.5848650336f, + 0.5847095251f, 0.5845539570f, 0.5843983293f, 0.5842427611f, 0.5840871334f, + 0.5839314461f, 0.5837758183f, 0.5836200714f, 0.5834643841f, 0.5833086371f, + 0.5831528902f, 0.5829970837f, 0.5828412771f, 0.5826854706f, 0.5825296640f, + 0.5823737979f, 0.5822178721f, 0.5820620060f, 0.5819060802f, 0.5817500949f, + 0.5815941095f, 0.5814381242f, 0.5812821388f, 0.5811260939f, 0.5809700489f, + 0.5808139443f, 0.5806578398f, 0.5805017352f, 0.5803455710f, 0.5801894069f, + 0.5800332427f, 0.5798770189f, 0.5797207952f, 0.5795645714f, 0.5794082880f, + 0.5792520046f, 0.5790956616f, 0.5789393187f, 0.5787829757f, 0.5786265731f, + 0.5784701705f, 0.5783137679f, 0.5781573057f, 0.5780009031f, 0.5778443813f, + 0.5776878595f, 0.5775313377f, 0.5773748159f, 0.5772182345f, 0.5770616531f, + 0.5769050121f, 0.5767484307f, 0.5765917301f, 0.5764350891f, 0.5762783885f, + 0.5761216879f, 0.5759649277f, 0.5758081675f, 0.5756514072f, 0.5754945874f, + 0.5753377676f, 0.5751808882f, 0.5750240684f, 0.5748671293f, 0.5747102499f, + 0.5745533109f, 0.5743963718f, 0.5742393732f, 0.5740824342f, 0.5739253759f, + 0.5737683773f, 0.5736113191f, 0.5734542012f, 0.5732971430f, 0.5731400251f, + 0.5729828477f, 0.5728257298f, 0.5726685524f, 0.5725113153f, 0.5723540783f, + 0.5721968412f, 0.5720396042f, 0.5718823075f, 0.5717250109f, 0.5715676546f, + 0.5714102983f, 0.5712529421f, 0.5710955262f, 0.5709381104f, 0.5707806945f, + 0.5706232786f, 0.5704658031f, 0.5703082681f, 0.5701507330f, 0.5699931979f, + 0.5698356628f, 0.5696780682f, 0.5695204735f, 0.5693628788f, 0.5692052245f, + 0.5690475702f, 0.5688898563f, 0.5687322021f, 0.5685744882f, 0.5684167147f, + 0.5682589412f, 0.5681011677f, 0.5679433346f, 0.5677855015f, 0.5676276684f, + 0.5674697757f, 0.5673118830f, 0.5671539903f, 0.5669960380f, 0.5668380857f, + 0.5666801333f, 0.5665221214f, 0.5663641095f, 0.5662060380f, 0.5660479665f, + 0.5658898950f, 0.5657318234f, 0.5655736923f, 0.5654155016f, 0.5652573705f, + 0.5650991797f, 0.5649409890f, 0.5647827387f, 0.5646244884f, 0.5644662380f, + 0.5643079281f, 0.5641496181f, 0.5639913082f, 0.5638329387f, 0.5636745691f, + 0.5635161996f, 0.5633577704f, 0.5631993413f, 0.5630408525f, 0.5628824234f, + 0.5627238750f, 0.5625653863f, 0.5624068379f, 0.5622482896f, 0.5620896816f, + 0.5619311333f, 0.5617724657f, 0.5616138577f, 0.5614551902f, 0.5612965226f, + 0.5611377954f, 0.5609790683f, 0.5608203411f, 0.5606615543f, 0.5605027676f, + 0.5603439808f, 0.5601851344f, 0.5600262880f, 0.5598674417f, 0.5597085357f, + 0.5595496297f, 0.5593906641f, 0.5592317581f, 0.5590727329f, 0.5589137673f, + 0.5587547421f, 0.5585957170f, 0.5584366918f, 0.5582776070f, 0.5581185222f, + 0.5579593778f, 0.5578002334f, 0.5576410890f, 0.5574818850f, 0.5573227406f, + 0.5571634769f, 0.5570042729f, 0.5568450093f, 0.5566857457f, 0.5565264225f, + 0.5563670993f, 0.5562077761f, 0.5560483932f, 0.5558890104f, 0.5557296276f, + 0.5555701852f, 0.5554107428f, 0.5552513003f, 0.5550917983f, 0.5549322963f, + 0.5547727942f, 0.5546132326f, 0.5544536710f, 0.5542941093f, 0.5541344881f, + 0.5539748669f, 0.5538151860f, 0.5536555052f, 0.5534958243f, 0.5533361435f, + 0.5531764030f, 0.5530166626f, 0.5528569221f, 0.5526971221f, 0.5525373220f, + 0.5523774624f, 0.5522176027f, 0.5520577431f, 0.5518978834f, 0.5517379642f, + 0.5515779853f, 0.5514180660f, 0.5512580872f, 0.5510981679f, 0.5509381294f, + 0.5507780910f, 0.5506180525f, 0.5504579544f, 0.5502978563f, 0.5501377583f, + 0.5499776602f, 0.5498175025f, 0.5496572852f, 0.5494971275f, 0.5493369102f, + 0.5491766334f, 0.5490164161f, 0.5488561392f, 0.5486958027f, 0.5485355258f, + 0.5483751893f, 0.5482147932f, 0.5480544567f, 0.5478940606f, 0.5477336645f, + 0.5475732088f, 0.5474127531f, 0.5472522378f, 0.5470917821f, 0.5469312668f, + 0.5467706919f, 0.5466101766f, 0.5464496017f, 0.5462889671f, 0.5461283326f, + 0.5459676981f, 0.5458070636f, 0.5456463695f, 0.5454856753f, 0.5453249812f, + 0.5451642275f, 0.5450034738f, 0.5448427200f, 0.5446819067f, 0.5445210934f, + 0.5443602204f, 0.5441994071f, 0.5440385342f, 0.5438776016f, 0.5437166691f, + 0.5435557365f, 0.5433948040f, 0.5432338119f, 0.5430728197f, 0.5429118276f, + 0.5427507758f, 0.5425897241f, 0.5424286127f, 0.5422675014f, 0.5421063900f, + 0.5419452786f, 0.5417841077f, 0.5416229367f, 0.5414617658f, 0.5413005352f, + 0.5411393046f, 0.5409780145f, 0.5408167243f, 0.5406554341f, 0.5404941440f, + 0.5403327942f, 0.5401715040f, 0.5400100946f, 0.5398487449f, 0.5396872759f, + 0.5395258665f, 0.5393643379f, 0.5392029285f, 0.5390414000f, 0.5388799310f, + 0.5387183428f, 0.5385568142f, 0.5383952260f, 0.5382336378f, 0.5380719900f, + 0.5379104018f, 0.5377486944f, 0.5375871062f, 0.5374253392f, 0.5372636914f, + 0.5371019244f, 0.5369402170f, 0.5367783904f, 0.5366166234f, 0.5364547968f, + 0.5362929702f, 0.5361310840f, 0.5359692574f, 0.5358073115f, 0.5356454849f, + 0.5354834795f, 0.5353215933f, 0.5351595879f, 0.5349976420f, 0.5348355770f, + 0.5346735716f, 0.5345115066f, 0.5343494415f, 0.5341873169f, 0.5340252519f, + 0.5338631272f, 0.5337010026f, 0.5335388184f, 0.5333766341f, 0.5332143903f, + 0.5330522060f, 0.5328899026f, 0.5327277184f, 0.5325653553f, 0.5324031115f, + 0.5322407484f, 0.5320784450f, 0.5319160223f, 0.5317537189f, 0.5315912366f, + 0.5314288735f, 0.5312663913f, 0.5311039686f, 0.5309414864f, 0.5307790041f, + 0.5306164622f, 0.5304539800f, 0.5302913785f, 0.5301288366f, 0.5299661756f, + 0.5298036337f, 0.5296409130f, 0.5294783115f, 0.5293155909f, 0.5291529894f, + 0.5289902091f, 0.5288274884f, 0.5286647081f, 0.5285019875f, 0.5283391476f, + 0.5281763673f, 0.5280135274f, 0.5278506875f, 0.5276877880f, 0.5275249481f, + 0.5273619890f, 0.5271991491f, 0.5270361304f, 0.5268732309f, 0.5267101526f, + 0.5265471935f, 0.5263841152f, 0.5262211561f, 0.5260580182f, 0.5258949995f, + 0.5257318616f, 0.5255687833f, 0.5254055858f, 0.5252425075f, 0.5250792503f, + 0.5249161124f, 0.5247528553f, 0.5245896578f, 0.5244263411f, 0.5242631435f, + 0.5240998864f, 0.5239365101f, 0.5237732530f, 0.5236098170f, 0.5234465003f, + 0.5232830644f, 0.5231196880f, 0.5229562521f, 0.5227928162f, 0.5226293206f, + 0.5224658847f, 0.5223023295f, 0.5221388340f, 0.5219752789f, 0.5218117237f, + 0.5216481090f, 0.5214845538f, 0.5213208795f, 0.5211573243f, 0.5209935904f, + 0.5208299756f, 0.5206662416f, 0.5205025673f, 0.5203387737f, 0.5201750398f, + 0.5200112462f, 0.5198475122f, 0.5196836591f, 0.5195198655f, 0.5193559527f, + 0.5191921592f, 0.5190281868f, 0.5188643336f, 0.5187003613f, 0.5185364485f, + 0.5183724165f, 0.5182085037f, 0.5180444717f, 0.5178804994f, 0.5177164078f, + 0.5175523758f, 0.5173882842f, 0.5172241926f, 0.5170600414f, 0.5168959498f, + 0.5167317390f, 0.5165676475f, 0.5164033771f, 0.5162392259f, 0.5160749555f, + 0.5159107447f, 0.5157464147f, 0.5155822039f, 0.5154178143f, 0.5152535439f, + 0.5150891542f, 0.5149248242f, 0.5147604346f, 0.5145960450f, 0.5144315958f, + 0.5142672062f, 0.5141026974f, 0.5139382482f, 0.5137737393f, 0.5136092305f, + 0.5134446621f, 0.5132801533f, 0.5131155252f, 0.5129510164f, 0.5127863288f, + 0.5126217604f, 0.5124570727f, 0.5122924447f, 0.5121276975f, 0.5119630694f, + 0.5117982626f, 0.5116335750f, 0.5114687681f, 0.5113040805f, 0.5111392140f, + 0.5109744668f, 0.5108095407f, 0.5106447339f, 0.5104798079f, 0.5103150010f, + 0.5101500154f, 0.5099851489f, 0.5098201632f, 0.5096552372f, 0.5094901919f, + 0.5093252659f, 0.5091601610f, 0.5089951754f, 0.5088300705f, 0.5086650252f, + 0.5084999204f, 0.5083348155f, 0.5081696510f, 0.5080045462f, 0.5078393221f, + 0.5076741576f, 0.5075089335f, 0.5073437691f, 0.5071784258f, 0.5070132017f, + 0.5068479180f, 0.5066826344f, 0.5065172911f, 0.5063520074f, 0.5061865449f, + 0.5060212612f, 0.5058559179f, 0.5056904554f, 0.5055250525f, 0.5053595304f, + 0.5051941276f, 0.5050286055f, 0.5048631430f, 0.5046975613f, 0.5045320392f, + 0.5043664575f, 0.5042009354f, 0.5040352345f, 0.5038697124f, 0.5037040114f, + 0.5035384297f, 0.5033726692f, 0.5032070279f, 0.5030412674f, 0.5028755665f, + 0.5027098060f, 0.5025441051f, 0.5023782253f, 0.5022124648f, 0.5020465851f, + 0.5018808246f, 0.5017149448f, 0.5015490651f, 0.5013831258f, 0.5012172461f, + 0.5010513067f, 0.5008853674f, 0.5007193685f, 0.5005534291f, 0.5003873706f, + 0.5002214313f, 0.5000553131f, 0.4998892844f, 0.4997231662f, 0.4995571077f, + 0.4993909597f, 0.4992248714f, 0.4990586638f, 0.4988925457f, 0.4987263083f, + 0.4985601306f, 0.4983938634f, 0.4982276559f, 0.4980613589f, 0.4978951216f, + 0.4977287650f, 0.4975624979f, 0.4973961115f, 0.4972298145f, 0.4970633984f, + 0.4968970418f, 0.4967305958f, 0.4965642095f, 0.4963977039f, 0.4962312877f, + 0.4960647523f, 0.4958983064f, 0.4957317412f, 0.4955652654f, 0.4953986406f, + 0.4952321351f, 0.4950654805f, 0.4948989153f, 0.4947322607f, 0.4945656359f, + 0.4943989217f, 0.4942322969f, 0.4940655529f, 0.4938988686f, 0.4937320948f, + 0.4935653806f, 0.4933985472f, 0.4932318330f, 0.4930649698f, 0.4928981662f, + 0.4927312732f, 0.4925644696f, 0.4923975468f, 0.4922306836f, 0.4920637012f, + 0.4918968379f, 0.4917298257f, 0.4915629029f, 0.4913958609f, 0.4912289083f, + 0.4910618067f, 0.4908948243f, 0.4907277226f, 0.4905606806f, 0.4903935194f, + 0.4902264774f, 0.4900592864f, 0.4898921847f, 0.4897249639f, 0.4895578027f, + 0.4893905520f, 0.4892233908f, 0.4890560806f, 0.4888888597f, 0.4887215495f, + 0.4885542989f, 0.4883869290f, 0.4882196486f, 0.4880522490f, 0.4878849387f, + 0.4877174795f, 0.4875501394f, 0.4873827696f, 0.4872152805f, 0.4870478511f, + 0.4868803322f, 0.4867129028f, 0.4865453243f, 0.4863778353f, 0.4862102568f, + 0.4860427380f, 0.4858750999f, 0.4857075512f, 0.4855398834f, 0.4853722751f, + 0.4852045774f, 0.4850369692f, 0.4848692119f, 0.4847015440f, 0.4845337868f, + 0.4843660891f, 0.4841982722f, 0.4840305448f, 0.4838626981f, 0.4836949408f, + 0.4835270345f, 0.4833592474f, 0.4831913114f, 0.4830234945f, 0.4828555286f, + 0.4826876521f, 0.4825196564f, 0.4823517501f, 0.4821837246f, 0.4820157886f, + 0.4818477333f, 0.4816797376f, 0.4815116525f, 0.4813436270f, 0.4811755121f, + 0.4810074568f, 0.4808392823f, 0.4806711972f, 0.4805029929f, 0.4803348780f, + 0.4801666439f, 0.4799984694f, 0.4798302054f, 0.4796620309f, 0.4794937074f, + 0.4793254733f, 0.4791571498f, 0.4789888859f, 0.4788205028f, 0.4786522090f, + 0.4784837961f, 0.4783154428f, 0.4781470001f, 0.4779786468f, 0.4778101444f, + 0.4776417613f, 0.4774732292f, 0.4773047864f, 0.4771362245f, 0.4769677520f, + 0.4767991602f, 0.4766306579f, 0.4764620364f, 0.4762935042f, 0.4761248231f, + 0.4759562612f, 0.4757875502f, 0.4756189585f, 0.4754502177f, 0.4752815664f, + 0.4751127958f, 0.4749441147f, 0.4747753143f, 0.4746066034f, 0.4744377732f, + 0.4742690325f, 0.4741001427f, 0.4739313722f, 0.4737624526f, 0.4735936522f, + 0.4734247029f, 0.4732558429f, 0.4730868638f, 0.4729179740f, 0.4727489650f, + 0.4725800455f, 0.4724109769f, 0.4722420275f, 0.4720729589f, 0.4719039500f, + 0.4717348516f, 0.4715658128f, 0.4713966548f, 0.4712275863f, 0.4710584283f, + 0.4708893299f, 0.4707201123f, 0.4705509543f, 0.4703817070f, 0.4702125490f, + 0.4700432420f, 0.4698740542f, 0.4697047174f, 0.4695354998f, 0.4693661332f, + 0.4691968560f, 0.4690275788f, 0.4688581824f, 0.4686888456f, 0.4685193896f, + 0.4683500528f, 0.4681805670f, 0.4680111706f, 0.4678416550f, 0.4676722288f, + 0.4675026834f, 0.4673332274f, 0.4671636522f, 0.4669941664f, 0.4668245316f, + 0.4666550159f, 0.4664853513f, 0.4663158059f, 0.4661461115f, 0.4659765065f, + 0.4658067822f, 0.4656371474f, 0.4654673934f, 0.4652977586f, 0.4651279449f, + 0.4649582505f, 0.4647884369f, 0.4646186829f, 0.4644488394f, 0.4642790854f, + 0.4641091824f, 0.4639393687f, 0.4637694657f, 0.4635996222f, 0.4634296596f, + 0.4632597864f, 0.4630897939f, 0.4629198909f, 0.4627498686f, 0.4625799358f, + 0.4624098539f, 0.4622398913f, 0.4620698094f, 0.4618997872f, 0.4617296755f, + 0.4615596235f, 0.4613894522f, 0.4612194002f, 0.4610491991f, 0.4608790874f, + 0.4607088566f, 0.4605387151f, 0.4603684545f, 0.4601982832f, 0.4600279629f, + 0.4598577619f, 0.4596874416f, 0.4595171809f, 0.4593468308f, 0.4591765404f, + 0.4590061307f, 0.4588358402f, 0.4586654007f, 0.4584950507f, 0.4583245814f, + 0.4581542015f, 0.4579837024f, 0.4578132927f, 0.4576427639f, 0.4574723244f, + 0.4573017359f, 0.4571312666f, 0.4569606781f, 0.4567901492f, 0.4566195309f, + 0.4564489722f, 0.4562782943f, 0.4561077356f, 0.4559370279f, 0.4557664096f, + 0.4555956721f, 0.4554250240f, 0.4552542567f, 0.4550835788f, 0.4549127817f, + 0.4547420442f, 0.4545712173f, 0.4544004798f, 0.4542295933f, 0.4540588260f, + 0.4538879097f, 0.4537171125f, 0.4535461664f, 0.4533753097f, 0.4532043338f, + 0.4530334771f, 0.4528624713f, 0.4526915550f, 0.4525205195f, 0.4523495734f, + 0.4521785080f, 0.4520075023f, 0.4518364072f, 0.4516654015f, 0.4514942467f, + 0.4513232112f, 0.4511520565f, 0.4509809613f, 0.4508097470f, 0.4506386518f, + 0.4504674077f, 0.4502962530f, 0.4501250982f, 0.4499538243f, 0.4497826099f, + 0.4496113062f, 0.4494400620f, 0.4492687285f, 0.4490974545f, 0.4489260614f, + 0.4487547874f, 0.4485833645f, 0.4484120309f, 0.4482405782f, 0.4480692148f, + 0.4478977323f, 0.4477263391f, 0.4475548267f, 0.4473834038f, 0.4472118318f, + 0.4470403790f, 0.4468688071f, 0.4466972947f, 0.4465256929f, 0.4463541806f, + 0.4461825192f, 0.4460109472f, 0.4458392859f, 0.4456676841f, 0.4454959631f, + 0.4453243613f, 0.4451526105f, 0.4449809492f, 0.4448091686f, 0.4446374774f, + 0.4444656670f, 0.4442939460f, 0.4441221058f, 0.4439503551f, 0.4437784553f, + 0.4436066747f, 0.4434347749f, 0.4432629347f, 0.4430910051f, 0.4429191649f, + 0.4427471757f, 0.4425753057f, 0.4424032867f, 0.4422313571f, 0.4420593381f, + 0.4418873787f, 0.4417153001f, 0.4415433109f, 0.4413712025f, 0.4411992133f, + 0.4410270751f, 0.4408550262f, 0.4406828284f, 0.4405107498f, 0.4403385520f, + 0.4401664436f, 0.4399942160f, 0.4398220778f, 0.4396497905f, 0.4394776225f, + 0.4393053353f, 0.4391331077f, 0.4389607906f, 0.4387885332f, 0.4386161864f, + 0.4384438992f, 0.4382715225f, 0.4380992055f, 0.4379267693f, 0.4377544224f, + 0.4375819862f, 0.4374096096f, 0.4372371137f, 0.4370647073f, 0.4368921816f, + 0.4367197454f, 0.4365471900f, 0.4363747239f, 0.4362021387f, 0.4360296428f, + 0.4358569980f, 0.4356844723f, 0.4355118275f, 0.4353392720f, 0.4351665676f, + 0.4349939823f, 0.4348212779f, 0.4346486330f, 0.4344758987f, 0.4343032241f, + 0.4341304600f, 0.4339577556f, 0.4337849319f, 0.4336122274f, 0.4334393740f, + 0.4332666099f, 0.4330937266f, 0.4329209626f, 0.4327480495f, 0.4325752258f, + 0.4324022830f, 0.4322294295f, 0.4320564568f, 0.4318835735f, 0.4317105711f, + 0.4315376580f, 0.4313646257f, 0.4311916828f, 0.4310187101f, 0.4308456481f, + 0.4306726456f, 0.4304995239f, 0.4303264916f, 0.4301533699f, 0.4299803078f, + 0.4298071265f, 0.4296340346f, 0.4294608235f, 0.4292877018f, 0.4291144609f, + 0.4289413095f, 0.4287680387f, 0.4285948575f, 0.4284215569f, 0.4282483459f, + 0.4280749857f, 0.4279017448f, 0.4277283847f, 0.4275551140f, 0.4273816943f, + 0.4272083938f, 0.4270349741f, 0.4268616438f, 0.4266881645f, 0.4265148044f, + 0.4263412952f, 0.4261679053f, 0.4259943664f, 0.4258209467f, 0.4256473780f, + 0.4254739285f, 0.4253003299f, 0.4251268506f, 0.4249532223f, 0.4247796834f, + 0.4246060252f, 0.4244324863f, 0.4242587984f, 0.4240851998f, 0.4239114821f, + 0.4237378836f, 0.4235641360f, 0.4233904779f, 0.4232167006f, 0.4230430126f, + 0.4228692055f, 0.4226954877f, 0.4225216508f, 0.4223479033f, 0.4221740365f, + 0.4220002592f, 0.4218263626f, 0.4216525555f, 0.4214786291f, 0.4213047922f, + 0.4211308360f, 0.4209569693f, 0.4207829833f, 0.4206090569f, 0.4204350412f, + 0.4202611148f, 0.4200870693f, 0.4199131131f, 0.4197390079f, 0.4195650220f, + 0.4193909168f, 0.4192168713f, 0.4190427363f, 0.4188686907f, 0.4186944962f, + 0.4185204208f, 0.4183461964f, 0.4181720912f, 0.4179978371f, 0.4178237021f, + 0.4176494181f, 0.4174752533f, 0.4173009396f, 0.4171267450f, 0.4169524014f, + 0.4167781770f, 0.4166038036f, 0.4164295495f, 0.4162551463f, 0.4160808623f, + 0.4159064293f, 0.4157320857f, 0.4155576527f, 0.4153832793f, 0.4152087867f, + 0.4150344133f, 0.4148598909f, 0.4146854579f, 0.4145109057f, 0.4143364727f, + 0.4141618907f, 0.4139873981f, 0.4138128161f, 0.4136382937f, 0.4134636521f, + 0.4132890999f, 0.4131144285f, 0.4129398763f, 0.4127651751f, 0.4125905633f, + 0.4124158323f, 0.4122411907f, 0.4120664299f, 0.4118917882f, 0.4117170870f, + 0.4115422964f, 0.4113675654f, 0.4111927450f, 0.4110180140f, 0.4108431339f, + 0.4106683731f, 0.4104934633f, 0.4103186727f, 0.4101437330f, 0.4099689126f, + 0.4097939730f, 0.4096190929f, 0.4094441235f, 0.4092692137f, 0.4090942144f, + 0.4089192748f, 0.4087442458f, 0.4085692763f, 0.4083942175f, 0.4082192183f, + 0.4080441296f, 0.4078691006f, 0.4076939821f, 0.4075189233f, 0.4073437750f, + 0.4071686864f, 0.4069935083f, 0.4068183899f, 0.4066431820f, 0.4064680338f, + 0.4062927961f, 0.4061176181f, 0.4059423506f, 0.4057671428f, 0.4055918455f, + 0.4054166079f, 0.4052412510f, 0.4050660133f, 0.4048906267f, 0.4047153592f, + 0.4045399427f, 0.4043646455f, 0.4041891992f, 0.4040138721f, 0.4038383961f, + 0.4036630392f, 0.4034875333f, 0.4033121467f, 0.4031366110f, 0.4029611945f, + 0.4027856290f, 0.4026101828f, 0.4024345875f, 0.4022591114f, 0.4020834863f, + 0.4019079804f, 0.4017323256f, 0.4015567899f, 0.4013811052f, 0.4012055397f, + 0.4010298252f, 0.4008542299f, 0.4006784856f, 0.4005028605f, 0.4003271163f, + 0.4001514316f, 0.3999756575f, 0.3997999430f, 0.3996241391f, 0.3994484246f, + 0.3992725611f, 0.3990968168f, 0.3989209235f, 0.3987451494f, 0.3985692561f, + 0.3983934224f, 0.3982174993f, 0.3980416656f, 0.3978656828f, 0.3976898193f, + 0.3975138068f, 0.3973379135f, 0.3971619010f, 0.3969859779f, 0.3968099058f, + 0.3966339529f, 0.3964578807f, 0.3962818980f, 0.3961057663f, 0.3959297538f, + 0.3957536221f, 0.3955775797f, 0.3954013884f, 0.3952253163f, 0.3950491250f, + 0.3948730230f, 0.3946968019f, 0.3945206702f, 0.3943444192f, 0.3941682577f, + 0.3939919472f, 0.3938157558f, 0.3936394453f, 0.3934632242f, 0.3932868838f, + 0.3931106329f, 0.3929342628f, 0.3927579820f, 0.3925815821f, 0.3924052715f, + 0.3922289610f, 0.3920525312f, 0.3918761611f, 0.3916997015f, 0.3915233016f, + 0.3913468122f, 0.3911704123f, 0.3909938633f, 0.3908174336f, 0.3906408846f, + 0.3904644251f, 0.3902878165f, 0.3901113272f, 0.3899347186f, 0.3897581995f, + 0.3895815313f, 0.3894049823f, 0.3892283142f, 0.3890517354f, 0.3888750374f, + 0.3886984289f, 0.3885217011f, 0.3883450627f, 0.3881683052f, 0.3879916370f, + 0.3878148496f, 0.3876381516f, 0.3874613345f, 0.3872846067f, 0.3871077597f, + 0.3869310021f, 0.3867541254f, 0.3865773678f, 0.3864004612f, 0.3862236440f, + 0.3860467076f, 0.3858698905f, 0.3856929243f, 0.3855160475f, 0.3853390813f, + 0.3851621747f, 0.3849851489f, 0.3848082423f, 0.3846311867f, 0.3844542503f, + 0.3842771649f, 0.3841001987f, 0.3839230835f, 0.3837460876f, 0.3835689723f, + 0.3833919168f, 0.3832147717f, 0.3830377162f, 0.3828605115f, 0.3826834261f, + 0.3825062215f, 0.3823291063f, 0.3821518421f, 0.3819746971f, 0.3817974329f, + 0.3816202581f, 0.3814429641f, 0.3812657595f, 0.3810884356f, 0.3809112012f, + 0.3807338476f, 0.3805565834f, 0.3803792000f, 0.3802019358f, 0.3800245225f, + 0.3798471987f, 0.3796697557f, 0.3794924021f, 0.3793149590f, 0.3791375756f, + 0.3789600730f, 0.3787826896f, 0.3786051571f, 0.3784277439f, 0.3782501817f, + 0.3780727386f, 0.3778951466f, 0.3777176738f, 0.3775400817f, 0.3773625493f, + 0.3771849275f, 0.3770073950f, 0.3768297434f, 0.3766521513f, 0.3764744699f, + 0.3762968779f, 0.3761191666f, 0.3759415448f, 0.3757638037f, 0.3755861521f, + 0.3754083812f, 0.3752306998f, 0.3750528991f, 0.3748752177f, 0.3746973872f, + 0.3745196462f, 0.3743417859f, 0.3741640449f, 0.3739861548f, 0.3738083839f, + 0.3736304641f, 0.3734526336f, 0.3732747138f, 0.3730968535f, 0.3729189038f, + 0.3727410436f, 0.3725631535f, 0.3723851442f, 0.3722072244f, 0.3720292151f, + 0.3718512654f, 0.3716731966f, 0.3714952469f, 0.3713171482f, 0.3711391687f, + 0.3709610403f, 0.3707830310f, 0.3706049025f, 0.3704268336f, 0.3702486753f, + 0.3700706065f, 0.3698924184f, 0.3697143197f, 0.3695360720f, 0.3693579435f, + 0.3691796958f, 0.3690015376f, 0.3688232601f, 0.3686451018f, 0.3684667945f, + 0.3682885766f, 0.3681102395f, 0.3679320216f, 0.3677536547f, 0.3675753772f, + 0.3673970103f, 0.3672187030f, 0.3670403063f, 0.3668619692f, 0.3666835427f, + 0.3665052056f, 0.3663267195f, 0.3661483526f, 0.3659698665f, 0.3657914698f, + 0.3656129539f, 0.3654345274f, 0.3652559817f, 0.3650775254f, 0.3648989499f, + 0.3647204638f, 0.3645418584f, 0.3643633723f, 0.3641847372f, 0.3640061915f, + 0.3638275564f, 0.3636489809f, 0.3634703159f, 0.3632917106f, 0.3631130159f, + 0.3629344106f, 0.3627556562f, 0.3625770211f, 0.3623982668f, 0.3622196019f, + 0.3620408177f, 0.3618621230f, 0.3616833091f, 0.3615045846f, 0.3613257408f, + 0.3611469865f, 0.3609681427f, 0.3607893586f, 0.3606104553f, 0.3604316711f, + 0.3602527380f, 0.3600739241f, 0.3598949611f, 0.3597161174f, 0.3595371544f, + 0.3593582511f, 0.3591792583f, 0.3590003550f, 0.3588213325f, 0.3586423993f, + 0.3584633470f, 0.3582843840f, 0.3581053019f, 0.3579263389f, 0.3577472270f, + 0.3575682044f, 0.3573890924f, 0.3572100401f, 0.3570308983f, 0.3568518162f, + 0.3566726446f, 0.3564935625f, 0.3563143313f, 0.3561352193f, 0.3559559882f, + 0.3557768464f, 0.3555975854f, 0.3554184139f, 0.3552391231f, 0.3550599217f, + 0.3548806310f, 0.3547013998f, 0.3545220494f, 0.3543428183f, 0.3541634381f, + 0.3539841771f, 0.3538047671f, 0.3536254764f, 0.3534460664f, 0.3532667458f, + 0.3530872762f, 0.3529079556f, 0.3527285755f, 0.3525491059f, 0.3523696959f, + 0.3521901965f, 0.3520107865f, 0.3518312573f, 0.3516518176f, 0.3514722288f, + 0.3512927890f, 0.3511132002f, 0.3509337008f, 0.3507540822f, 0.3505745530f, + 0.3503949344f, 0.3502153754f, 0.3500357270f, 0.3498561382f, 0.3496764600f, + 0.3494968712f, 0.3493171334f, 0.3491375148f, 0.3489577770f, 0.3487781286f, + 0.3485983610f, 0.3484186828f, 0.3482388854f, 0.3480592072f, 0.3478793800f, + 0.3476996422f, 0.3475198150f, 0.3473400772f, 0.3471601903f, 0.3469804227f, + 0.3468005061f, 0.3466207087f, 0.3464407921f, 0.3462609649f, 0.3460810184f, + 0.3459011912f, 0.3457212150f, 0.3455413282f, 0.3453613222f, 0.3451814353f, + 0.3450013995f, 0.3448214829f, 0.3446414173f, 0.3444614708f, 0.3442814052f, + 0.3441014290f, 0.3439213336f, 0.3437413275f, 0.3435612023f, 0.3433811665f, + 0.3432010114f, 0.3430209756f, 0.3428407907f, 0.3426607251f, 0.3424805105f, + 0.3423004150f, 0.3421201706f, 0.3419400454f, 0.3417598009f, 0.3415796459f, + 0.3413993716f, 0.3412191868f, 0.3410388827f, 0.3408586979f, 0.3406783640f, + 0.3404981196f, 0.3403177857f, 0.3401375413f, 0.3399571478f, 0.3397768736f, + 0.3395964801f, 0.3394161761f, 0.3392357230f, 0.3390554190f, 0.3388749659f, + 0.3386946023f, 0.3385141194f, 0.3383337557f, 0.3381532431f, 0.3379728496f, + 0.3377923071f, 0.3376118839f, 0.3374313414f, 0.3372508883f, 0.3370703161f, + 0.3368898332f, 0.3367092311f, 0.3365287185f, 0.3363481164f, 0.3361675739f, + 0.3359869123f, 0.3358063698f, 0.3356257081f, 0.3354451358f, 0.3352644145f, + 0.3350838125f, 0.3349030912f, 0.3347224593f, 0.3345417082f, 0.3343610764f, + 0.3341802955f, 0.3339996338f, 0.3338188231f, 0.3336381316f, 0.3334572911f, + 0.3332765698f, 0.3330958486f, 0.3329149783f, 0.3327342272f, 0.3325533271f, + 0.3323725462f, 0.3321916461f, 0.3320108354f, 0.3318299055f, 0.3316490650f, + 0.3314681053f, 0.3312872648f, 0.3311062753f, 0.3309253752f, 0.3307443857f, + 0.3305634856f, 0.3303824365f, 0.3302015066f, 0.3300204575f, 0.3298394978f, + 0.3296584189f, 0.3294774294f, 0.3292963505f, 0.3291153312f, 0.3289341927f, + 0.3287531734f, 0.3285720348f, 0.3283909857f, 0.3282097876f, 0.3280287087f, + 0.3278475106f, 0.3276664317f, 0.3274852037f, 0.3273040652f, 0.3271228075f, + 0.3269416690f, 0.3267604113f, 0.3265792429f, 0.3263979256f, 0.3262167275f, + 0.3260354102f, 0.3258541822f, 0.3256728649f, 0.3254916072f, 0.3253102303f, + 0.3251289725f, 0.3249475658f, 0.3247662783f, 0.3245848715f, 0.3244035542f, + 0.3242221177f, 0.3240407705f, 0.3238593042f, 0.3236779571f, 0.3234964609f, + 0.3233150542f, 0.3231335580f, 0.3229521513f, 0.3227705956f, 0.3225891888f, + 0.3224076033f, 0.3222261667f, 0.3220445812f, 0.3218630850f, 0.3216814995f, + 0.3214999735f, 0.3213183582f, 0.3211368322f, 0.3209551573f, 0.3207736015f, + 0.3205919266f, 0.3204103708f, 0.3202286661f, 0.3200470507f, 0.3198653460f, + 0.3196837008f, 0.3195019662f, 0.3193203211f, 0.3191385269f, 0.3189568818f, + 0.3187750876f, 0.3185933828f, 0.3184115589f, 0.3182298541f, 0.3180480003f, + 0.3178662658f, 0.3176843822f, 0.3175026178f, 0.3173207343f, 0.3171389699f, + 0.3169570565f, 0.3167752326f, 0.3165932894f, 0.3164114654f, 0.3162294924f, + 0.3160476387f, 0.3158656657f, 0.3156837821f, 0.3155017793f, 0.3153198659f, + 0.3151378334f, 0.3149559200f, 0.3147738576f, 0.3145919144f, 0.3144098520f, + 0.3142278790f, 0.3140457571f, 0.3138637841f, 0.3136816621f, 0.3134996295f, + 0.3133174777f, 0.3131354451f, 0.3129533827f, 0.3127712011f, 0.3125891387f, + 0.3124069273f, 0.3122248352f, 0.3120426238f, 0.3118605018f, 0.3116782308f, + 0.3114960790f, 0.3113138378f, 0.3111316562f, 0.3109493554f, 0.3107671738f, + 0.3105848432f, 0.3104026318f, 0.3102203012f, 0.3100380599f, 0.3098556995f, + 0.3096734285f, 0.3094910681f, 0.3093087673f, 0.3091263771f, 0.3089440465f, + 0.3087616265f, 0.3085792959f, 0.3083968461f, 0.3082144856f, 0.3080320358f, + 0.3078496456f, 0.3076671362f, 0.3074847460f, 0.3073022366f, 0.3071198165f, + 0.3069372773f, 0.3067548275f, 0.3065722585f, 0.3063898087f, 0.3062072098f, + 0.3060247302f, 0.3058421016f, 0.3056595922f, 0.3054769635f, 0.3052944541f, + 0.3051117957f, 0.3049292266f, 0.3047465384f, 0.3045639694f, 0.3043812811f, + 0.3041986823f, 0.3040159643f, 0.3038333356f, 0.3036505878f, 0.3034679294f, + 0.3032851815f, 0.3031025231f, 0.3029197156f, 0.3027370274f, 0.3025542200f, + 0.3023715019f, 0.3021886647f, 0.3020059466f, 0.3018230796f, 0.3016403317f, + 0.3014574647f, 0.3012746871f, 0.3010917604f, 0.3009089828f, 0.3007260561f, + 0.3005432189f, 0.3003602922f, 0.3001774549f, 0.2999944687f, 0.2998116016f, + 0.2996286154f, 0.2994457185f, 0.2992627323f, 0.2990798056f, 0.2988967896f, + 0.2987138331f, 0.2985307872f, 0.2983478308f, 0.2981647551f, 0.2979817986f, + 0.2977986932f, 0.2976156771f, 0.2974325716f, 0.2972495556f, 0.2970663905f, + 0.2968833745f, 0.2967002094f, 0.2965171337f, 0.2963339388f, 0.2961508632f, + 0.2959676683f, 0.2957845628f, 0.2956013083f, 0.2954182029f, 0.2952349484f, + 0.2950517833f, 0.2948685288f, 0.2946853340f, 0.2945020497f, 0.2943188548f, + 0.2941355407f, 0.2939523160f, 0.2937689722f, 0.2935857475f, 0.2934023738f, + 0.2932191193f, 0.2930357456f, 0.2928524613f, 0.2926691771f, 0.2924857736f, + 0.2923024595f, 0.2921190262f, 0.2919356823f, 0.2917522192f, 0.2915688753f, + 0.2913853824f, 0.2912020087f, 0.2910185158f, 0.2908351123f, 0.2906515896f, + 0.2904681861f, 0.2902846336f, 0.2901012003f, 0.2899176180f, 0.2897341847f, + 0.2895505726f, 0.2893671095f, 0.2891834974f, 0.2890000045f, 0.2888163626f, + 0.2886328399f, 0.2884491980f, 0.2882656455f, 0.2880819738f, 0.2878983915f, + 0.2877147198f, 0.2875311375f, 0.2873474061f, 0.2871637940f, 0.2869800627f, + 0.2867964208f, 0.2866126895f, 0.2864290178f, 0.2862452567f, 0.2860615849f, + 0.2858777940f, 0.2856940925f, 0.2855102718f, 0.2853265405f, 0.2851427197f, + 0.2849589884f, 0.2847751081f, 0.2845913470f, 0.2844074667f, 0.2842237055f, + 0.2840397954f, 0.2838560045f, 0.2836720645f, 0.2834882438f, 0.2833043039f, + 0.2831204832f, 0.2829365134f, 0.2827526331f, 0.2825686634f, 0.2823847830f, + 0.2822007835f, 0.2820168734f, 0.2818328440f, 0.2816489339f, 0.2814648747f, + 0.2812809348f, 0.2810968459f, 0.2809129059f, 0.2807288170f, 0.2805448174f, + 0.2803606987f, 0.2801766992f, 0.2799925804f, 0.2798085511f, 0.2796244025f, + 0.2794403434f, 0.2792561650f, 0.2790721059f, 0.2788879275f, 0.2787038386f, + 0.2785196006f, 0.2783355117f, 0.2781512737f, 0.2779671550f, 0.2777828872f, + 0.2775987387f, 0.2774144709f, 0.2772302926f, 0.2770459950f, 0.2768618166f, + 0.2766774893f, 0.2764932811f, 0.2763089538f, 0.2761247158f, 0.2759403586f, + 0.2757561207f, 0.2755717337f, 0.2753874660f, 0.2752030790f, 0.2750187814f, + 0.2748343647f, 0.2746500373f, 0.2744656205f, 0.2742812932f, 0.2740968168f, + 0.2739124596f, 0.2737279832f, 0.2735436261f, 0.2733591199f, 0.2731747329f, + 0.2729902267f, 0.2728058100f, 0.2726212740f, 0.2724368274f, 0.2722523808f, + 0.2720678151f, 0.2718833685f, 0.2716987729f, 0.2715142965f, 0.2713296711f, + 0.2711451650f, 0.2709605396f, 0.2707760334f, 0.2705913782f, 0.2704068422f, + 0.2702221572f, 0.2700376213f, 0.2698529363f, 0.2696683407f, 0.2694836259f, + 0.2692990303f, 0.2691143155f, 0.2689296901f, 0.2687449455f, 0.2685602903f, + 0.2683755159f, 0.2681908607f, 0.2680060863f, 0.2678214014f, 0.2676365972f, + 0.2674518824f, 0.2672670782f, 0.2670823634f, 0.2668974996f, 0.2667127550f, + 0.2665278912f, 0.2663431466f, 0.2661582530f, 0.2659734786f, 0.2657885849f, + 0.2656037807f, 0.2654188573f, 0.2652340233f, 0.2650490999f, 0.2648642659f, + 0.2646792829f, 0.2644944191f, 0.2643094361f, 0.2641245723f, 0.2639395595f, + 0.2637546659f, 0.2635696530f, 0.2633847296f, 0.2631996870f, 0.2630147636f, + 0.2628297210f, 0.2626447678f, 0.2624596655f, 0.2622747123f, 0.2620896101f, + 0.2619045973f, 0.2617194951f, 0.2615344822f, 0.2613493502f, 0.2611643076f, + 0.2609791458f, 0.2607941031f, 0.2606089413f, 0.2604238689f, 0.2602386773f, + 0.2600535750f, 0.2598683536f, 0.2596832514f, 0.2594980299f, 0.2593128979f, + 0.2591276467f, 0.2589425147f, 0.2587572336f, 0.2585720718f, 0.2583867908f, + 0.2582015991f, 0.2580162883f, 0.2578310966f, 0.2576457560f, 0.2574605346f, + 0.2572751939f, 0.2570899427f, 0.2569045722f, 0.2567193210f, 0.2565339506f, + 0.2563486695f, 0.2561632693f, 0.2559779584f, 0.2557925284f, 0.2556072176f, + 0.2554217875f, 0.2552364469f, 0.2550509870f, 0.2548656464f, 0.2546801567f, + 0.2544947863f, 0.2543092966f, 0.2541238964f, 0.2539383769f, 0.2537529767f, + 0.2535674274f, 0.2533819973f, 0.2531964481f, 0.2530110180f, 0.2528254390f, + 0.2526399791f, 0.2524543703f, 0.2522688806f, 0.2520832717f, 0.2518977821f, + 0.2517122626f, 0.2515266240f, 0.2513411045f, 0.2511554360f, 0.2509698868f, + 0.2507842183f, 0.2505986691f, 0.2504129708f, 0.2502273917f, 0.2500416636f, + 0.2498560697f, 0.2496703416f, 0.2494847178f, 0.2492989749f, 0.2491133213f, + 0.2489275634f, 0.2487419099f, 0.2485561222f, 0.2483704388f, 0.2481846362f, + 0.2479989380f, 0.2478131205f, 0.2476274073f, 0.2474415749f, 0.2472558320f, + 0.2470699847f, 0.2468842268f, 0.2466983497f, 0.2465125918f, 0.2463266999f, + 0.2461409122f, 0.2459549904f, 0.2457691878f, 0.2455832660f, 0.2453974485f, + 0.2452114969f, 0.2450256497f, 0.2448396832f, 0.2446538359f, 0.2444678396f, + 0.2442819625f, 0.2440959662f, 0.2439100742f, 0.2437240481f, 0.2435381413f, + 0.2433521003f, 0.2431661785f, 0.2429801226f, 0.2427941710f, 0.2426081002f, + 0.2424221337f, 0.2422360480f, 0.2420500517f, 0.2418639511f, 0.2416779399f, + 0.2414918244f, 0.2413057983f, 0.2411196530f, 0.2409336120f, 0.2407474518f, + 0.2405613959f, 0.2403752208f, 0.2401891500f, 0.2400029600f, 0.2398168594f, + 0.2396306545f, 0.2394445390f, 0.2392583042f, 0.2390721887f, 0.2388859391f, + 0.2386997938f, 0.2385135144f, 0.2383273542f, 0.2381410748f, 0.2379548997f, + 0.2377685905f, 0.2375824004f, 0.2373960763f, 0.2372098714f, 0.2370235324f, + 0.2368372977f, 0.2366509438f, 0.2364646941f, 0.2362783253f, 0.2360920608f, + 0.2359056622f, 0.2357193828f, 0.2355329841f, 0.2353466749f, 0.2351602465f, + 0.2349739373f, 0.2347874939f, 0.2346011549f, 0.2344146967f, 0.2342283428f, + 0.2340418696f, 0.2338555008f, 0.2336690128f, 0.2334826291f, 0.2332961112f, + 0.2331097126f, 0.2329231799f, 0.2327367663f, 0.2325502187f, 0.2323637754f, + 0.2321772128f, 0.2319907546f, 0.2318041772f, 0.2316177040f, 0.2314311117f, + 0.2312446237f, 0.2310581356f, 0.2308715135f, 0.2306849957f, 0.2304983586f, + 0.2303118259f, 0.2301251739f, 0.2299386263f, 0.2297519445f, 0.2295653820f, + 0.2293787003f, 0.2291921079f, 0.2290054113f, 0.2288188040f, 0.2286320776f, + 0.2284454703f, 0.2282587290f, 0.2280720919f, 0.2278853357f, 0.2276986837f, + 0.2275119126f, 0.2273252457f, 0.2271384597f, 0.2269517779f, 0.2267649770f, + 0.2265782654f, 0.2263914496f, 0.2262047380f, 0.2260178924f, 0.2258311659f, + 0.2256443053f, 0.2254575491f, 0.2252706736f, 0.2250839174f, 0.2248970270f, + 0.2247102410f, 0.2245233357f, 0.2243365347f, 0.2241496146f, 0.2239627987f, + 0.2237758636f, 0.2235890329f, 0.2234020680f, 0.2232152224f, 0.2230282575f, + 0.2228413820f, 0.2226544023f, 0.2224675119f, 0.2222805172f, 0.2220936120f, + 0.2219065875f, 0.2217196822f, 0.2215326428f, 0.2213457078f, 0.2211586535f, + 0.2209717184f, 0.2207846493f, 0.2205976844f, 0.2204106003f, 0.2202236205f, + 0.2200365067f, 0.2198495120f, 0.2196623981f, 0.2194753885f, 0.2192882597f, + 0.2191012204f, 0.2189140767f, 0.2187270373f, 0.2185398638f, 0.2183528095f, + 0.2181656212f, 0.2179785520f, 0.2177913487f, 0.2176042646f, 0.2174170464f, + 0.2172299325f, 0.2170426995f, 0.2168555856f, 0.2166683376f, 0.2164811939f, + 0.2162939310f, 0.2161067724f, 0.2159194946f, 0.2157323211f, 0.2155450284f, + 0.2153578401f, 0.2151705325f, 0.2149833292f, 0.2147960067f, 0.2146087885f, + 0.2144214362f, 0.2142342031f, 0.2140468508f, 0.2138596028f, 0.2136722207f, + 0.2134849578f, 0.2132975757f, 0.2131102830f, 0.2129228860f, 0.2127355933f, + 0.2125481665f, 0.2123608589f, 0.2121734172f, 0.2119860947f, 0.2117986381f, + 0.2116112858f, 0.2114238292f, 0.2112364620f, 0.2110489756f, 0.2108616084f, + 0.2106742263f, 0.2104867250f, 0.2102993131f, 0.2101117969f, 0.2099243850f, + 0.2097368538f, 0.2095494121f, 0.2093618661f, 0.2091744244f, 0.2089868486f, + 0.2087993920f, 0.2086118162f, 0.2084243298f, 0.2082367390f, 0.2080492377f, + 0.2078616321f, 0.2076741308f, 0.2074864954f, 0.2072989792f, 0.2071113288f, + 0.2069237977f, 0.2067361325f, 0.2065485865f, 0.2063609064f, 0.2061733454f, + 0.2059856504f, 0.2057980746f, 0.2056103647f, 0.2054227591f, 0.2052350491f, + 0.2050474286f, 0.2048596889f, 0.2046720684f, 0.2044843137f, 0.2042966783f, + 0.2041089088f, 0.2039212584f, 0.2037334740f, 0.2035457939f, 0.2033580095f, + 0.2031703144f, 0.2029825002f, 0.2027948052f, 0.2026069760f, 0.2024192661f, + 0.2022314221f, 0.2020436972f, 0.2018558383f, 0.2016680837f, 0.2014802098f, + 0.2012924552f, 0.2011045665f, 0.2009167969f, 0.2007288933f, 0.2005411088f, + 0.2003531903f, 0.2001653761f, 0.1999774575f, 0.1997896284f, 0.1996016949f, + 0.1994138509f, 0.1992259026f, 0.1990380436f, 0.1988500655f, 0.1986622065f, + 0.1984742135f, 0.1982863396f, 0.1980983317f, 0.1979104429f, 0.1977224201f, + 0.1975345165f, 0.1973464936f, 0.1971585602f, 0.1969705224f, 0.1967825890f, + 0.1965945214f, 0.1964065731f, 0.1962184906f, 0.1960305274f, 0.1958424449f, + 0.1956544518f, 0.1954663545f, 0.1952783614f, 0.1950902343f, 0.1949022263f, + 0.1947140992f, 0.1945260763f, 0.1943379343f, 0.1941498965f, 0.1939617246f, + 0.1937736720f, 0.1935855001f, 0.1933974326f, 0.1932092458f, 0.1930211633f, + 0.1928329617f, 0.1926448643f, 0.1924566478f, 0.1922685355f, 0.1920803040f, + 0.1918921918f, 0.1917039305f, 0.1915158033f, 0.1913275421f, 0.1911393851f, + 0.1909511089f, 0.1907629520f, 0.1905746609f, 0.1903864890f, 0.1901981831f, + 0.1900099814f, 0.1898217797f, 0.1896334589f, 0.1894452423f, 0.1892569065f, + 0.1890686899f, 0.1888803244f, 0.1886920929f, 0.1885037273f, 0.1883154660f, + 0.1881270856f, 0.1879388243f, 0.1877504289f, 0.1875621378f, 0.1873737425f, + 0.1871854365f, 0.1869970113f, 0.1868087053f, 0.1866202652f, 0.1864319444f, + 0.1862435043f, 0.1860551685f, 0.1858666986f, 0.1856783479f, 0.1854898781f, + 0.1853015125f, 0.1851130128f, 0.1849246323f, 0.1847361326f, 0.1845477372f, + 0.1843592227f, 0.1841708273f, 0.1839822829f, 0.1837938726f, 0.1836053282f, + 0.1834168881f, 0.1832283288f, 0.1830398887f, 0.1828513145f, 0.1826628596f, + 0.1824742705f, 0.1822858006f, 0.1820971966f, 0.1819087118f, 0.1817201078f, + 0.1815316081f, 0.1813429743f, 0.1811544746f, 0.1809658259f, 0.1807772964f, + 0.1805886477f, 0.1804001182f, 0.1802114546f, 0.1800228953f, 0.1798342168f, + 0.1796456575f, 0.1794569641f, 0.1792683750f, 0.1790796816f, 0.1788910776f, + 0.1787023693f, 0.1785137653f, 0.1783250272f, 0.1781364083f, 0.1779476702f, + 0.1777590364f, 0.1775702834f, 0.1773816347f, 0.1771928668f, 0.1770042032f, + 0.1768154204f, 0.1766267568f, 0.1764379591f, 0.1762492657f, 0.1760604680f, + 0.1758717597f, 0.1756829470f, 0.1754942387f, 0.1753053963f, 0.1751166731f, + 0.1749278307f, 0.1747390926f, 0.1745502353f, 0.1743614823f, 0.1741726100f, + 0.1739838421f, 0.1737949699f, 0.1736061871f, 0.1734172851f, 0.1732285023f, + 0.1730395854f, 0.1728507876f, 0.1726618707f, 0.1724730581f, 0.1722841263f, + 0.1720952988f, 0.1719063371f, 0.1717175096f, 0.1715285480f, 0.1713396907f, + 0.1711507142f, 0.1709618568f, 0.1707728654f, 0.1705839932f, 0.1703949869f, + 0.1702060997f, 0.1700170934f, 0.1698281914f, 0.1696391702f, 0.1694502532f, + 0.1692612171f, 0.1690722853f, 0.1688833535f, 0.1686943024f, 0.1685053557f, + 0.1683162898f, 0.1681273282f, 0.1679382473f, 0.1677492857f, 0.1675601900f, + 0.1673712134f, 0.1671821028f, 0.1669931114f, 0.1668040007f, 0.1666149944f, + 0.1664258540f, 0.1662368327f, 0.1660476923f, 0.1658586711f, 0.1656695157f, + 0.1654804647f, 0.1652913094f, 0.1651022434f, 0.1649130732f, 0.1647240072f, + 0.1645348072f, 0.1643457264f, 0.1641565263f, 0.1639674455f, 0.1637782305f, + 0.1635891199f, 0.1633998901f, 0.1632107794f, 0.1630215347f, 0.1628324091f, + 0.1626431644f, 0.1624540240f, 0.1622647643f, 0.1620756090f, 0.1618863344f, + 0.1616971791f, 0.1615078896f, 0.1613187045f, 0.1611294150f, 0.1609402299f, + 0.1607509106f, 0.1605617106f, 0.1603723913f, 0.1601831913f, 0.1599938571f, + 0.1598046273f, 0.1596152782f, 0.1594260484f, 0.1592366844f, 0.1590474397f, + 0.1588580757f, 0.1586688161f, 0.1584794372f, 0.1582901627f, 0.1581007838f, + 0.1579114944f, 0.1577220857f, 0.1575327963f, 0.1573433876f, 0.1571540833f, + 0.1569646597f, 0.1567753404f, 0.1565859020f, 0.1563965678f, 0.1562071145f, + 0.1560177803f, 0.1558283269f, 0.1556389779f, 0.1554494947f, 0.1552601308f, + 0.1550706476f, 0.1548812836f, 0.1546917856f, 0.1545024067f, 0.1543128937f, + 0.1541235000f, 0.1539339721f, 0.1537445784f, 0.1535550356f, 0.1533656269f, + 0.1531760842f, 0.1529866606f, 0.1527971029f, 0.1526076645f, 0.1524180919f, + 0.1522286385f, 0.1520390660f, 0.1518496126f, 0.1516600251f, 0.1514705420f, + 0.1512809545f, 0.1510914713f, 0.1509018540f, 0.1507123560f, 0.1505227387f, + 0.1503332257f, 0.1501436085f, 0.1499540806f, 0.1497644484f, 0.1495749056f, + 0.1493852586f, 0.1491957158f, 0.1490060538f, 0.1488165110f, 0.1486268342f, + 0.1484372616f, 0.1482475847f, 0.1480580121f, 0.1478684247f, 0.1476787329f, + 0.1474891454f, 0.1472994238f, 0.1471098214f, 0.1469200999f, 0.1467304975f, + 0.1465407610f, 0.1463511288f, 0.1461613923f, 0.1459717602f, 0.1457819939f, + 0.1455923617f, 0.1454025954f, 0.1452129334f, 0.1450231522f, 0.1448334903f, + 0.1446437091f, 0.1444540322f, 0.1442642361f, 0.1440745443f, 0.1438847333f, + 0.1436950415f, 0.1435052156f, 0.1433155090f, 0.1431256831f, 0.1429359615f, + 0.1427461207f, 0.1425563991f, 0.1423665434f, 0.1421768069f, 0.1419869512f, + 0.1417971998f, 0.1416073292f, 0.1414175630f, 0.1412276775f, 0.1410379112f, + 0.1408480257f, 0.1406582445f, 0.1404683292f, 0.1402785480f, 0.1400886327f, + 0.1398988366f, 0.1397089064f, 0.1395190954f, 0.1393291652f, 0.1391393393f, + 0.1389493942f, 0.1387595683f, 0.1385696083f, 0.1383797675f, 0.1381898075f, + 0.1379999518f, 0.1378099769f, 0.1376201063f, 0.1374301314f, 0.1372402608f, + 0.1370502561f, 0.1368603706f, 0.1366703659f, 0.1364804804f, 0.1362904608f, + 0.1361005604f, 0.1359105408f, 0.1357206255f, 0.1355305910f, 0.1353406608f, + 0.1351506263f, 0.1349606812f, 0.1347706318f, 0.1345806867f, 0.1343906224f, + 0.1342006773f, 0.1340105981f, 0.1338206381f, 0.1336305439f, 0.1334405839f, + 0.1332504898f, 0.1330605000f, 0.1328703910f, 0.1326804012f, 0.1324902922f, + 0.1323002875f, 0.1321101636f, 0.1319201589f, 0.1317300200f, 0.1315400004f, + 0.1313498616f, 0.1311598271f, 0.1309696734f, 0.1307796389f, 0.1305894703f, + 0.1303994209f, 0.1302092522f, 0.1300191879f, 0.1298290044f, 0.1296389401f, + 0.1294487566f, 0.1292586774f, 0.1290684640f, 0.1288783848f, 0.1286881715f, + 0.1284980774f, 0.1283078492f, 0.1281177551f, 0.1279275119f, 0.1277374029f, + 0.1275471598f, 0.1273570359f, 0.1271667928f, 0.1269766539f, 0.1267865151f, + 0.1265962571f, 0.1264061034f, 0.1262158304f, 0.1260256767f, 0.1258353889f, + 0.1256452352f, 0.1254549325f, 0.1252647638f, 0.1250744611f, 0.1248842776f, + 0.1246939674f, 0.1245037764f, 0.1243134588f, 0.1241232529f, 0.1239329278f, + 0.1237427145f, 0.1235523745f, 0.1233621538f, 0.1231718138f, 0.1229815781f, + 0.1227912232f, 0.1226009876f, 0.1224106252f, 0.1222203746f, 0.1220299974f, + 0.1218397394f, 0.1216493621f, 0.1214590967f, 0.1212687045f, 0.1210784316f, + 0.1208880320f, 0.1206977442f, 0.1205073372f, 0.1203170419f, 0.1201266274f, + 0.1199363247f, 0.1197458953f, 0.1195555851f, 0.1193651557f, 0.1191748306f, + 0.1189843863f, 0.1187940612f, 0.1186036095f, 0.1184132695f, 0.1182228103f, + 0.1180324629f, 0.1178419963f, 0.1176516414f, 0.1174611598f, 0.1172707975f, + 0.1170803159f, 0.1168899387f, 0.1166994423f, 0.1165090650f, 0.1163185611f, + 0.1161281690f, 0.1159376577f, 0.1157472581f, 0.1155567393f, 0.1153663322f, + 0.1151758060f, 0.1149853915f, 0.1147948503f, 0.1146044284f, 0.1144138798f, + 0.1142234504f, 0.1140328944f, 0.1138424575f, 0.1136518940f, 0.1134614423f, + 0.1132708713f, 0.1130804196f, 0.1128898337f, 0.1126993746f, 0.1125087813f, + 0.1123183072f, 0.1121277139f, 0.1119372323f, 0.1117466316f, 0.1115561351f, + 0.1113655269f, 0.1111750305f, 0.1109844074f, 0.1107939035f, 0.1106032729f, + 0.1104127541f, 0.1102221161f, 0.1100315973f, 0.1098409519f, 0.1096504182f, + 0.1094597653f, 0.1092692316f, 0.1090785712f, 0.1088880226f, 0.1086973548f, + 0.1085067987f, 0.1083161235f, 0.1081255600f, 0.1079348698f, 0.1077442989f, + 0.1075536087f, 0.1073630303f, 0.1071723253f, 0.1069817394f, 0.1067910343f, + 0.1066004410f, 0.1064097211f, 0.1062191203f, 0.1060283929f, 0.1058377847f, + 0.1056471691f, 0.1054564342f, 0.1052658111f, 0.1050750688f, 0.1048844382f, + 0.1046936885f, 0.1045030504f, 0.1043122932f, 0.1041216478f, 0.1039308831f, + 0.1037402302f, 0.1035494506f, 0.1033587903f, 0.1031680107f, 0.1029773429f, + 0.1027865559f, 0.1025958806f, 0.1024050787f, 0.1022143960f, 0.1020235941f, + 0.1018329039f, 0.1016420871f, 0.1014513895f, 0.1012605727f, 0.1010698676f, + 0.1008790433f, 0.1006883308f, 0.1004974917f, 0.1003067717f, 0.1001159325f, + 0.0999252051f, 0.0997343510f, 0.0995436162f, 0.0993527621f, 0.0991620198f, + 0.0989711583f, 0.0987804085f, 0.0985895321f, 0.0983987823f, 0.0982078984f, + 0.0980171338f, 0.0978262499f, 0.0976354778f, 0.0974445865f, 0.0972538069f, + 0.0970629081f, 0.0968721211f, 0.0966812149f, 0.0964904204f, 0.0962995067f, + 0.0961087123f, 0.0959177911f, 0.0957269818f, 0.0955360532f, 0.0953452364f, + 0.0951543003f, 0.0949634835f, 0.0947725400f, 0.0945817158f, 0.0943907648f, + 0.0941999257f, 0.0940089747f, 0.0938181281f, 0.0936271697f, 0.0934363157f, + 0.0932453498f, 0.0930544958f, 0.0928635150f, 0.0926726535f, 0.0924816728f, + 0.0922908038f, 0.0920998082f, 0.0919089317f, 0.0917179361f, 0.0915270522f, + 0.0913360491f, 0.0911451653f, 0.0909541547f, 0.0907632560f, 0.0905722380f, + 0.0903813392f, 0.0901903138f, 0.0899994001f, 0.0898083746f, 0.0896174535f, + 0.0894264206f, 0.0892354921f, 0.0890444517f, 0.0888535231f, 0.0886624753f, + 0.0884715393f, 0.0882804766f, 0.0880895406f, 0.0878984779f, 0.0877075270f, + 0.0875164568f, 0.0873254985f, 0.0871344209f, 0.0869434625f, 0.0867523775f, + 0.0865614116f, 0.0863703266f, 0.0861793533f, 0.0859882534f, 0.0857972726f, + 0.0856061727f, 0.0854151845f, 0.0852240771f, 0.0850330815f, 0.0848419666f, + 0.0846509710f, 0.0844599679f, 0.0842688456f, 0.0840778351f, 0.0838867053f, + 0.0836956948f, 0.0835045576f, 0.0833135322f, 0.0831223950f, 0.0829313695f, + 0.0827402174f, 0.0825491846f, 0.0823580325f, 0.0821669921f, 0.0819758326f, + 0.0817847848f, 0.0815936178f, 0.0814025700f, 0.0812113956f, 0.0810203403f, + 0.0808291584f, 0.0806380957f, 0.0804469138f, 0.0802558437f, 0.0800646544f, + 0.0798735768f, 0.0796823800f, 0.0794913024f, 0.0793000981f, 0.0791090131f, + 0.0789178014f, 0.0787267163f, 0.0785354972f, 0.0783444047f, 0.0781531781f, + 0.0779620782f, 0.0777708516f, 0.0775797442f, 0.0773885101f, 0.0771973953f, + 0.0770061612f, 0.0768150389f, 0.0766237974f, 0.0764326677f, 0.0762414262f, + 0.0760502890f, 0.0758590400f, 0.0756679028f, 0.0754766390f, 0.0752854943f, + 0.0750942305f, 0.0749030858f, 0.0747118145f, 0.0745206624f, 0.0743293837f, + 0.0741382241f, 0.0739469454f, 0.0737557784f, 0.0735644922f, 0.0733733177f, + 0.0731820315f, 0.0729908496f, 0.0727995560f, 0.0726083741f, 0.0724170730f, + 0.0722258836f, 0.0720345750f, 0.0718433857f, 0.0716520697f, 0.0714608729f, + 0.0712695569f, 0.0710783526f, 0.0708870292f, 0.0706958175f, 0.0705044940f, + 0.0703132823f, 0.0701219440f, 0.0699307248f, 0.0697393864f, 0.0695481673f, + 0.0693568215f, 0.0691655874f, 0.0689742416f, 0.0687830076f, 0.0685916543f, + 0.0684004128f, 0.0682090521f, 0.0680178106f, 0.0678264499f, 0.0676352009f, + 0.0674438328f, 0.0672525764f, 0.0670612007f, 0.0668699443f, 0.0666785613f, + 0.0664872974f, 0.0662959144f, 0.0661046505f, 0.0659132600f, 0.0657219887f, + 0.0655305907f, 0.0653393120f, 0.0651479140f, 0.0649566278f, 0.0647652298f, + 0.0645739436f, 0.0643825307f, 0.0641912371f, 0.0639998242f, 0.0638085306f, + 0.0636172295f, 0.0634258091f, 0.0632345080f, 0.0630430803f, 0.0628517717f, + 0.0626603439f, 0.0624690317f, 0.0622775964f, 0.0620862767f, 0.0618948378f, + 0.0617035180f, 0.0615120754f, 0.0613207482f, 0.0611292981f, 0.0609379672f, + 0.0607465170f, 0.0605551787f, 0.0603637248f, 0.0601723827f, 0.0599809214f, + 0.0597895756f, 0.0595981106f, 0.0594067611f, 0.0592152923f, 0.0590239391f, + 0.0588324666f, 0.0586411059f, 0.0584496297f, 0.0582582653f, 0.0580667853f, + 0.0578754172f, 0.0576839298f, 0.0574925616f, 0.0573010668f, 0.0571096949f, + 0.0569181964f, 0.0567268208f, 0.0565353185f, 0.0563439354f, 0.0561524332f, + 0.0559610464f, 0.0557695366f, 0.0555781461f, 0.0553866327f, 0.0551952384f, + 0.0550037213f, 0.0548123233f, 0.0546208024f, 0.0544293970f, 0.0542378724f, + 0.0540464669f, 0.0538549386f, 0.0536635257f, 0.0534719937f, 0.0532805808f, + 0.0530890413f, 0.0528976247f, 0.0527060851f, 0.0525146611f, 0.0523231179f, + 0.0521316901f, 0.0519401431f, 0.0517487116f, 0.0515571609f, 0.0513657257f, + 0.0511741675f, 0.0509827323f, 0.0507911704f, 0.0505997315f, 0.0504081659f, + 0.0502167195f, 0.0500251539f, 0.0498337038f, 0.0496421345f, 0.0494506806f, + 0.0492591076f, 0.0490676500f, 0.0488760732f, 0.0486846119f, 0.0484930314f, + 0.0483015664f, 0.0481099822f, 0.0479185171f, 0.0477269255f, 0.0475354567f, + 0.0473438650f, 0.0471523888f, 0.0469607934f, 0.0467693172f, 0.0465777181f, + 0.0463862382f, 0.0461946353f, 0.0460031480f, 0.0458115451f, 0.0456200577f, + 0.0454284474f, 0.0452369563f, 0.0450453423f, 0.0448538475f, 0.0446622334f, + 0.0444707349f, 0.0442791171f, 0.0440876149f, 0.0438959934f, 0.0437044874f, + 0.0435128622f, 0.0433213562f, 0.0431297272f, 0.0429382175f, 0.0427465849f, + 0.0425550714f, 0.0423635542f, 0.0421719179f, 0.0419804007f, 0.0417887606f, + 0.0415972397f, 0.0414055958f, 0.0412140712f, 0.0410224237f, 0.0408308990f, + 0.0406392477f, 0.0404477194f, 0.0402560644f, 0.0400645323f, 0.0398728773f, + 0.0396813415f, 0.0394896828f, 0.0392981432f, 0.0391064845f, 0.0389149413f, + 0.0387232788f, 0.0385317318f, 0.0383400656f, 0.0381485187f, 0.0379568487f, + 0.0377652980f, 0.0375736281f, 0.0373820737f, 0.0371903963f, 0.0369988419f, + 0.0368071645f, 0.0366156064f, 0.0364239253f, 0.0362323634f, 0.0360406823f, + 0.0358491167f, 0.0356574319f, 0.0354658626f, 0.0352741778f, 0.0350826047f, + 0.0348909162f, 0.0346993431f, 0.0345076509f, 0.0343160741f, 0.0341243818f, + 0.0339328013f, 0.0337411053f, 0.0335495248f, 0.0333578251f, 0.0331662409f, + 0.0329745375f, 0.0327829532f, 0.0325912498f, 0.0323996618f, 0.0322079547f, + 0.0320163630f, 0.0318246558f, 0.0316330604f, 0.0314413495f, 0.0312497560f, + 0.0310580414f, 0.0308664441f, 0.0306747276f, 0.0304831285f, 0.0302914083f, + 0.0300998073f, 0.0299080871f, 0.0297164842f, 0.0295247603f, 0.0293331537f, + 0.0291414279f, 0.0289498214f, 0.0287580937f, 0.0285664834f, 0.0283747539f, + 0.0281831417f, 0.0279914085f, 0.0277997945f, 0.0276080612f, 0.0274164453f, + 0.0272247083f, 0.0270330906f, 0.0268413536f, 0.0266497321f, 0.0264579933f, + 0.0262663718f, 0.0260746293f, 0.0258830059f, 0.0256912615f, 0.0254996344f, + 0.0253078900f, 0.0251162611f, 0.0249245148f, 0.0247328840f, 0.0245411359f, + 0.0243495032f, 0.0241577532f, 0.0239661187f, 0.0237743668f, 0.0235827323f, + 0.0233909767f, 0.0231993403f, 0.0230075847f, 0.0228159465f, 0.0226241872f, + 0.0224325471f, 0.0222407877f, 0.0220491458f, 0.0218573846f, 0.0216657408f, + 0.0214739777f, 0.0212823339f, 0.0210906882f, 0.0208989233f, 0.0207072757f, + 0.0205155089f, 0.0203238595f, 0.0201320909f, 0.0199404415f, 0.0197486710f, + 0.0195570197f, 0.0193652492f, 0.0191735961f, 0.0189818218f, 0.0187901687f, + 0.0185983945f, 0.0184067376f, 0.0182149634f, 0.0180233065f, 0.0178315286f, + 0.0176398698f, 0.0174480919f, 0.0172564331f, 0.0170646533f, 0.0168729927f, + 0.0166812111f, 0.0164895486f, 0.0162977669f, 0.0161061045f, 0.0159143209f, + 0.0157226566f, 0.0155308722f, 0.0153392060f, 0.0151474206f, 0.0149557535f, + 0.0147639671f, 0.0145722991f, 0.0143805118f, 0.0141888428f, 0.0139970537f, + 0.0138053838f, 0.0136135947f, 0.0134219229f, 0.0132301329f, 0.0130384602f, + 0.0128466692f, 0.0126549955f, 0.0124632036f, 0.0122715291f, 0.0120797362f, + 0.0118880607f, 0.0116962669f, 0.0115045914f, 0.0113127958f, 0.0111211194f, + 0.0109293228f, 0.0107376464f, 0.0105458489f, 0.0103541706f, 0.0101623731f, + 0.0099706948f, 0.0097788963f, 0.0095872162f, 0.0093954178f, 0.0092037376f, + 0.0090119373f, 0.0088202562f, 0.0086284559f, 0.0084367748f, 0.0082449736f, + 0.0080532916f, 0.0078614894f, 0.0076698069f, 0.0074780043f, 0.0072863214f, + 0.0070945183f, 0.0069028344f, 0.0067110313f, 0.0065193470f, 0.0063275429f, + 0.0061358581f, 0.0059440541f, 0.0057523688f, 0.0055605643f, 0.0053688786f, + 0.0051770732f, 0.0049853874f, 0.0047935820f, 0.0046018953f, 0.0044100895f, + 0.0042184028f, 0.0040265969f, 0.0038349098f, 0.0036431034f, 0.0034514160f, + 0.0032596092f, 0.0030679218f, 0.0028761148f, 0.0026844270f, 0.0024926199f, + 0.0023009321f, 0.0021091248f, 0.0019174365f, 0.0017256291f, 0.0015339408f, + 0.0013421333f, 0.0011504448f, 0.0009586373f, 0.0007669488f, 0.0005751411f, + 0.0003834526f, 0.0001916448f +#elif TWIDDLE_TABLE_ORDER == 12 + 1.0000000000f, 0.9999988235f, 0.9999952938f, 0.9999894111f, 0.9999811753f, + 0.9999705864f, 0.9999576446f, 0.9999423497f, 0.9999247018f, 0.9999047011f, + 0.9998823475f, 0.9998576410f, 0.9998305818f, 0.9998011699f, 0.9997694054f, + 0.9997352883f, 0.9996988187f, 0.9996599967f, 0.9996188225f, 0.9995752960f, + 0.9995294175f, 0.9994811870f, 0.9994306046f, 0.9993776704f, 0.9993223846f, + 0.9992647473f, 0.9992047586f, 0.9991424187f, 0.9990777278f, 0.9990106859f, + 0.9989412932f, 0.9988695499f, 0.9987954562f, 0.9987190122f, 0.9986402182f, + 0.9985590742f, 0.9984755806f, 0.9983897374f, 0.9983015449f, 0.9982110034f, + 0.9981181129f, 0.9980228738f, 0.9979252862f, 0.9978253504f, 0.9977230666f, + 0.9976184351f, 0.9975114561f, 0.9974021299f, 0.9972904567f, 0.9971764367f, + 0.9970600703f, 0.9969413578f, 0.9968202993f, 0.9966968952f, 0.9965711458f, + 0.9964430514f, 0.9963126122f, 0.9961798286f, 0.9960447009f, 0.9959072294f, + 0.9957674145f, 0.9956252564f, 0.9954807555f, 0.9953339121f, 0.9951847267f, + 0.9950331994f, 0.9948793308f, 0.9947231211f, 0.9945645707f, 0.9944036801f, + 0.9942404495f, 0.9940748793f, 0.9939069700f, 0.9937367219f, 0.9935641355f, + 0.9933892111f, 0.9932119492f, 0.9930323502f, 0.9928504145f, 0.9926661424f, + 0.9924795346f, 0.9922905913f, 0.9920993131f, 0.9919057004f, 0.9917097537f, + 0.9915114733f, 0.9913108598f, 0.9911079137f, 0.9909026354f, 0.9906950254f, + 0.9904850843f, 0.9902728124f, 0.9900582103f, 0.9898412785f, 0.9896220175f, + 0.9894004278f, 0.9891765100f, 0.9889502645f, 0.9887216920f, 0.9884907929f, + 0.9882575677f, 0.9880220171f, 0.9877841416f, 0.9875439418f, 0.9873014182f, + 0.9870565713f, 0.9868094018f, 0.9865599103f, 0.9863080972f, 0.9860539633f, + 0.9857975092f, 0.9855387353f, 0.9852776424f, 0.9850142310f, 0.9847485018f, + 0.9844804554f, 0.9842100924f, 0.9839374134f, 0.9836624192f, 0.9833851103f, + 0.9831054874f, 0.9828235512f, 0.9825393023f, 0.9822527414f, 0.9819638691f, + 0.9816726862f, 0.9813791933f, 0.9810833912f, 0.9807852804f, 0.9804848618f, + 0.9801821360f, 0.9798771037f, 0.9795697657f, 0.9792601226f, 0.9789481753f, + 0.9786339244f, 0.9783173707f, 0.9779985149f, 0.9776773578f, 0.9773539001f, + 0.9770281427f, 0.9767000861f, 0.9763697313f, 0.9760370790f, 0.9757021300f, + 0.9753648851f, 0.9750253451f, 0.9746835107f, 0.9743393828f, 0.9739929622f, + 0.9736442497f, 0.9732932461f, 0.9729399522f, 0.9725843689f, 0.9722264971f, + 0.9718663375f, 0.9715038910f, 0.9711391584f, 0.9707721407f, 0.9704028387f, + 0.9700312532f, 0.9696573851f, 0.9692812354f, 0.9689028048f, 0.9685220943f, + 0.9681391047f, 0.9677538371f, 0.9673662922f, 0.9669764710f, 0.9665843745f, + 0.9661900034f, 0.9657933589f, 0.9653944417f, 0.9649932529f, 0.9645897933f, + 0.9641840640f, 0.9637760658f, 0.9633657998f, 0.9629532669f, 0.9625384680f, + 0.9621214043f, 0.9617020765f, 0.9612804858f, 0.9608566331f, 0.9604305194f, + 0.9600021457f, 0.9595715131f, 0.9591386225f, 0.9587034749f, 0.9582660714f, + 0.9578264130f, 0.9573845008f, 0.9569403357f, 0.9564939189f, 0.9560452513f, + 0.9555943341f, 0.9551411683f, 0.9546857549f, 0.9542280951f, 0.9537681899f, + 0.9533060404f, 0.9528416476f, 0.9523750127f, 0.9519061368f, 0.9514350210f, + 0.9509616663f, 0.9504860739f, 0.9500082450f, 0.9495281806f, 0.9490458819f, + 0.9485613499f, 0.9480745859f, 0.9475855910f, 0.9470943664f, 0.9466009131f, + 0.9461052324f, 0.9456073254f, 0.9451071933f, 0.9446048373f, 0.9441002585f, + 0.9435934582f, 0.9430844375f, 0.9425731976f, 0.9420597398f, 0.9415440652f, + 0.9410261751f, 0.9405060706f, 0.9399837530f, 0.9394592236f, 0.9389324835f, + 0.9384035341f, 0.9378723764f, 0.9373390119f, 0.9368034417f, 0.9362656672f, + 0.9357256895f, 0.9351835099f, 0.9346391298f, 0.9340925504f, 0.9335437730f, + 0.9329927988f, 0.9324396293f, 0.9318842656f, 0.9313267091f, 0.9307669611f, + 0.9302050229f, 0.9296408958f, 0.9290745813f, 0.9285060805f, 0.9279353948f, + 0.9273625257f, 0.9267874743f, 0.9262102421f, 0.9256308305f, 0.9250492408f, + 0.9244654743f, 0.9238795325f, 0.9232914167f, 0.9227011283f, 0.9221086687f, + 0.9215140393f, 0.9209172415f, 0.9203182767f, 0.9197171463f, 0.9191138517f, + 0.9185083943f, 0.9179007756f, 0.9172909970f, 0.9166790599f, 0.9160649658f, + 0.9154487161f, 0.9148303122f, 0.9142097557f, 0.9135870479f, 0.9129621904f, + 0.9123351846f, 0.9117060320f, 0.9110747341f, 0.9104412923f, 0.9098057081f, + 0.9091679831f, 0.9085281187f, 0.9078861165f, 0.9072419779f, 0.9065957045f, + 0.9059472978f, 0.9052967593f, 0.9046440906f, 0.9039892931f, 0.9033323685f, + 0.9026733182f, 0.9020121439f, 0.9013488470f, 0.9006834292f, 0.9000158920f, + 0.8993462370f, 0.8986744657f, 0.8980005797f, 0.8973245807f, 0.8966464702f, + 0.8959662498f, 0.8952839210f, 0.8945994856f, 0.8939129451f, 0.8932243012f, + 0.8925335554f, 0.8918407094f, 0.8911457648f, 0.8904487232f, 0.8897495864f, + 0.8890483559f, 0.8883450333f, 0.8876396204f, 0.8869321188f, 0.8862225301f, + 0.8855108561f, 0.8847970984f, 0.8840812587f, 0.8833633387f, 0.8826433400f, + 0.8819212643f, 0.8811971135f, 0.8804708891f, 0.8797425928f, 0.8790122264f, + 0.8782797917f, 0.8775452902f, 0.8768087238f, 0.8760700942f, 0.8753294031f, + 0.8745866523f, 0.8738418435f, 0.8730949784f, 0.8723460589f, 0.8715950867f, + 0.8708420635f, 0.8700869911f, 0.8693298713f, 0.8685707060f, 0.8678094968f, + 0.8670462455f, 0.8662809540f, 0.8655136241f, 0.8647442575f, 0.8639728561f, + 0.8631994217f, 0.8624239561f, 0.8616464611f, 0.8608669386f, 0.8600853904f, + 0.8593018184f, 0.8585162243f, 0.8577286100f, 0.8569389774f, 0.8561473284f, + 0.8553536647f, 0.8545579884f, 0.8537603011f, 0.8529606049f, 0.8521589016f, + 0.8513551931f, 0.8505494813f, 0.8497417680f, 0.8489320552f, 0.8481203448f, + 0.8473066387f, 0.8464909388f, 0.8456732470f, 0.8448535652f, 0.8440318955f, + 0.8432082396f, 0.8423825996f, 0.8415549774f, 0.8407253750f, 0.8398937942f, + 0.8390602371f, 0.8382247056f, 0.8373872016f, 0.8365477272f, 0.8357062844f, + 0.8348628750f, 0.8340175011f, 0.8331701647f, 0.8323208678f, 0.8314696123f, + 0.8306164003f, 0.8297612338f, 0.8289041148f, 0.8280450453f, 0.8271840273f, + 0.8263210628f, 0.8254561540f, 0.8245893028f, 0.8237205112f, 0.8228497814f, + 0.8219771153f, 0.8211025150f, 0.8202259826f, 0.8193475201f, 0.8184671296f, + 0.8175848132f, 0.8167005729f, 0.8158144108f, 0.8149263291f, 0.8140363297f, + 0.8131444148f, 0.8122505866f, 0.8113548470f, 0.8104571983f, 0.8095576424f, + 0.8086561816f, 0.8077528179f, 0.8068475535f, 0.8059403906f, 0.8050313311f, + 0.8041203774f, 0.8032075315f, 0.8022927955f, 0.8013761717f, 0.8004576622f, + 0.7995372691f, 0.7986149946f, 0.7976908409f, 0.7967648102f, 0.7958369046f, + 0.7949071263f, 0.7939754776f, 0.7930419605f, 0.7921065773f, 0.7911693302f, + 0.7902302214f, 0.7892892532f, 0.7883464276f, 0.7874017470f, 0.7864552136f, + 0.7855068296f, 0.7845565972f, 0.7836045186f, 0.7826505962f, 0.7816948321f, + 0.7807372286f, 0.7797777879f, 0.7788165124f, 0.7778534042f, 0.7768884657f, + 0.7759216990f, 0.7749531066f, 0.7739826906f, 0.7730104534f, 0.7720363972f, + 0.7710605243f, 0.7700828370f, 0.7691033376f, 0.7681220285f, 0.7671389119f, + 0.7661539902f, 0.7651672656f, 0.7641787405f, 0.7631884173f, 0.7621962981f, + 0.7612023855f, 0.7602066817f, 0.7592091890f, 0.7582099098f, 0.7572088465f, + 0.7562060014f, 0.7552013769f, 0.7541949753f, 0.7531867990f, 0.7521768504f, + 0.7511651319f, 0.7501516458f, 0.7491363945f, 0.7481193805f, 0.7471006060f, + 0.7460800735f, 0.7450577854f, 0.7440337442f, 0.7430079521f, 0.7419804117f, + 0.7409511254f, 0.7399200955f, 0.7388873245f, 0.7378528148f, 0.7368165689f, + 0.7357785892f, 0.7347388781f, 0.7336974381f, 0.7326542717f, 0.7316093812f, + 0.7305627692f, 0.7295144381f, 0.7284643904f, 0.7274126286f, 0.7263591551f, + 0.7253039724f, 0.7242470830f, 0.7231884893f, 0.7221281939f, 0.7210661993f, + 0.7200025080f, 0.7189371224f, 0.7178700451f, 0.7168012785f, 0.7157308253f, + 0.7146586879f, 0.7135848688f, 0.7125093706f, 0.7114321957f, 0.7103533469f, + 0.7092728264f, 0.7081906370f, 0.7071067812f, 0.7060212614f, 0.7049340804f, + 0.7038452405f, 0.7027547445f, 0.7016625947f, 0.7005687939f, 0.6994733446f, + 0.6983762494f, 0.6972775108f, 0.6961771315f, 0.6950751140f, 0.6939714609f, + 0.6928661748f, 0.6917592584f, 0.6906507141f, 0.6895405447f, 0.6884287528f, + 0.6873153409f, 0.6862003117f, 0.6850836678f, 0.6839654118f, 0.6828455464f, + 0.6817240742f, 0.6806009978f, 0.6794763199f, 0.6783500431f, 0.6772221701f, + 0.6760927036f, 0.6749616461f, 0.6738290004f, 0.6726947691f, 0.6715589548f, + 0.6704215604f, 0.6692825883f, 0.6681420414f, 0.6669999223f, 0.6658562337f, + 0.6647109782f, 0.6635641586f, 0.6624157776f, 0.6612658378f, 0.6601143421f, + 0.6589612930f, 0.6578066933f, 0.6566505457f, 0.6554928530f, 0.6543336178f, + 0.6531728430f, 0.6520105311f, 0.6508466850f, 0.6496813074f, 0.6485144010f, + 0.6473459686f, 0.6461760130f, 0.6450045368f, 0.6438315429f, 0.6426570340f, + 0.6414810128f, 0.6403034822f, 0.6391244449f, 0.6379439036f, 0.6367618612f, + 0.6355783205f, 0.6343932842f, 0.6332067551f, 0.6320187359f, 0.6308292296f, + 0.6296382389f, 0.6284457666f, 0.6272518155f, 0.6260563884f, 0.6248594881f, + 0.6236611175f, 0.6224612794f, 0.6212599765f, 0.6200572118f, 0.6188529880f, + 0.6176473079f, 0.6164401745f, 0.6152315906f, 0.6140215589f, 0.6128100824f, + 0.6115971639f, 0.6103828063f, 0.6091670123f, 0.6079497850f, 0.6067311270f, + 0.6055110414f, 0.6042895309f, 0.6030665985f, 0.6018422471f, 0.6006164794f, + 0.5993892984f, 0.5981607070f, 0.5969307081f, 0.5956993045f, 0.5944664992f, + 0.5932322950f, 0.5919966950f, 0.5907597019f, 0.5895213186f, 0.5882815482f, + 0.5870403935f, 0.5857978575f, 0.5845539430f, 0.5833086529f, 0.5820619903f, + 0.5808139581f, 0.5795645591f, 0.5783137964f, 0.5770616729f, 0.5758081914f, + 0.5745533550f, 0.5732971667f, 0.5720396293f, 0.5707807459f, 0.5695205193f, + 0.5682589527f, 0.5669960488f, 0.5657318108f, 0.5644662415f, 0.5631993440f, + 0.5619311212f, 0.5606615762f, 0.5593907119f, 0.5581185312f, 0.5568450373f, + 0.5555702330f, 0.5542941215f, 0.5530167056f, 0.5517379884f, 0.5504579729f, + 0.5491766622f, 0.5478940592f, 0.5466101669f, 0.5453249884f, 0.5440385267f, + 0.5427507849f, 0.5414617659f, 0.5401714727f, 0.5388799085f, 0.5375870763f, + 0.5362929791f, 0.5349976199f, 0.5337010018f, 0.5324031279f, 0.5311040012f, + 0.5298036247f, 0.5285020015f, 0.5271991348f, 0.5258950275f, 0.5245896827f, + 0.5232831035f, 0.5219752929f, 0.5206662541f, 0.5193559902f, 0.5180445041f, + 0.5167317990f, 0.5154178780f, 0.5141027442f, 0.5127864006f, 0.5114688504f, + 0.5101500967f, 0.5088301425f, 0.5075089911f, 0.5061866453f, 0.5048631085f, + 0.5035383837f, 0.5022124740f, 0.5008853826f, 0.4995571125f, 0.4982276670f, + 0.4968970490f, 0.4955652618f, 0.4942323085f, 0.4928981922f, 0.4915629161f, + 0.4902264833f, 0.4888888969f, 0.4875501601f, 0.4862102761f, 0.4848692480f, + 0.4835270789f, 0.4821837721f, 0.4808393306f, 0.4794937577f, 0.4781470564f, + 0.4767992301f, 0.4754502817f, 0.4741002147f, 0.4727490320f, 0.4713967368f, + 0.4700433325f, 0.4686888220f, 0.4673332087f, 0.4659764958f, 0.4646186863f, + 0.4632597836f, 0.4618997907f, 0.4605387110f, 0.4591765475f, 0.4578133036f, + 0.4564489824f, 0.4550835871f, 0.4537171210f, 0.4523495872f, 0.4509809890f, + 0.4496113297f, 0.4482406123f, 0.4468688402f, 0.4454960165f, 0.4441221446f, + 0.4427472276f, 0.4413712687f, 0.4399942713f, 0.4386162385f, 0.4372371737f, + 0.4358570799f, 0.4344759606f, 0.4330938189f, 0.4317106580f, 0.4303264813f, + 0.4289412921f, 0.4275550934f, 0.4261678887f, 0.4247796812f, 0.4233904741f, + 0.4220002708f, 0.4206090744f, 0.4192168884f, 0.4178237158f, 0.4164295601f, + 0.4150344245f, 0.4136383122f, 0.4122412267f, 0.4108431711f, 0.4094441487f, + 0.4080441629f, 0.4066432169f, 0.4052413140f, 0.4038384576f, 0.4024346509f, + 0.4010298972f, 0.3996241998f, 0.3982175622f, 0.3968099874f, 0.3954014789f, + 0.3939920401f, 0.3925816741f, 0.3911703843f, 0.3897581741f, 0.3883450467f, + 0.3869310055f, 0.3855160538f, 0.3841001950f, 0.3826834324f, 0.3812657692f, + 0.3798472089f, 0.3784277548f, 0.3770074102f, 0.3755861785f, 0.3741640630f, + 0.3727410670f, 0.3713171940f, 0.3698924471f, 0.3684668300f, 0.3670403457f, + 0.3656129978f, 0.3641847896f, 0.3627557244f, 0.3613258056f, 0.3598950365f, + 0.3584634206f, 0.3570309612f, 0.3555976617f, 0.3541635254f, 0.3527285558f, + 0.3512927561f, 0.3498561298f, 0.3484186802f, 0.3469804108f, 0.3455413250f, + 0.3441014260f, 0.3426607173f, 0.3412192023f, 0.3397768844f, 0.3383337670f, + 0.3368898534f, 0.3354451471f, 0.3339996514f, 0.3325533699f, 0.3311063058f, + 0.3296584625f, 0.3282098436f, 0.3267604523f, 0.3253102922f, 0.3238593665f, + 0.3224076788f, 0.3209552324f, 0.3195020308f, 0.3180480774f, 0.3165933756f, + 0.3151379288f, 0.3136817404f, 0.3122248139f, 0.3107671527f, 0.3093087603f, + 0.3078496400f, 0.3063897954f, 0.3049292297f, 0.3034679466f, 0.3020059493f, + 0.3005432414f, 0.2990798263f, 0.2976157074f, 0.2961508882f, 0.2946853722f, + 0.2932191627f, 0.2917522632f, 0.2902846773f, 0.2888164082f, 0.2873474595f, + 0.2858778347f, 0.2844075372f, 0.2829365705f, 0.2814649379f, 0.2799926431f, + 0.2785196894f, 0.2770460803f, 0.2755718193f, 0.2740969099f, 0.2726213554f, + 0.2711451595f, 0.2696683256f, 0.2681908571f, 0.2667127575f, 0.2652340303f, + 0.2637546790f, 0.2622747070f, 0.2607941179f, 0.2593129151f, 0.2578311022f, + 0.2563486825f, 0.2548656596f, 0.2533820370f, 0.2518978182f, 0.2504130066f, + 0.2489276057f, 0.2474416192f, 0.2459550503f, 0.2444679027f, 0.2429801799f, + 0.2414918853f, 0.2400030224f, 0.2385135948f, 0.2370236060f, 0.2355330594f, + 0.2340419586f, 0.2325503070f, 0.2310581083f, 0.2295653658f, 0.2280720832f, + 0.2265782638f, 0.2250839114f, 0.2235890292f, 0.2220936210f, 0.2205976901f, + 0.2191012402f, 0.2176042746f, 0.2161067971f, 0.2146088110f, 0.2131103199f, + 0.2116113274f, 0.2101118369f, 0.2086118520f, 0.2071113762f, 0.2056104131f, + 0.2041089661f, 0.2026070388f, 0.2011046348f, 0.1996017576f, 0.1980984107f, + 0.1965945977f, 0.1950903220f, 0.1935855873f, 0.1920803970f, 0.1905747548f, + 0.1890686641f, 0.1875621286f, 0.1860551517f, 0.1845477369f, 0.1830398880f, + 0.1815316083f, 0.1800229014f, 0.1785137709f, 0.1770042204f, 0.1754942534f, + 0.1739838734f, 0.1724730840f, 0.1709618888f, 0.1694502912f, 0.1679382950f, + 0.1664259035f, 0.1649131205f, 0.1633999494f, 0.1618863938f, 0.1603724572f, + 0.1588581433f, 0.1573434556f, 0.1558283977f, 0.1543129730f, 0.1527971853f, + 0.1512810380f, 0.1497645347f, 0.1482476790f, 0.1467304745f, 0.1452129247f, + 0.1436950332f, 0.1421768035f, 0.1406582393f, 0.1391393442f, 0.1376201216f, + 0.1361005752f, 0.1345807085f, 0.1330605252f, 0.1315400287f, 0.1300192227f, + 0.1284981108f, 0.1269766965f, 0.1254549834f, 0.1239329751f, 0.1224106752f, + 0.1208880872f, 0.1193652148f, 0.1178420615f, 0.1163186309f, 0.1147949266f, + 0.1132709522f, 0.1117467112f, 0.1102222073f, 0.1086974440f, 0.1071724250f, + 0.1056471537f, 0.1041216339f, 0.1025958690f, 0.1010698628f, 0.0995436187f, + 0.0980171403f, 0.0964904314f, 0.0949634953f, 0.0934363358f, 0.0919089565f, + 0.0903813609f, 0.0888535526f, 0.0873255352f, 0.0857973123f, 0.0842688876f, + 0.0827402645f, 0.0812114468f, 0.0796824380f, 0.0781532416f, 0.0766238614f, + 0.0750943008f, 0.0735645636f, 0.0720346532f, 0.0705045734f, 0.0689743276f, + 0.0674439196f, 0.0659133528f, 0.0643826309f, 0.0628517576f, 0.0613207363f, + 0.0597895707f, 0.0582582645f, 0.0567268212f, 0.0551952443f, 0.0536635377f, + 0.0521317047f, 0.0505997490f, 0.0490676743f, 0.0475354842f, 0.0460031821f, + 0.0444707719f, 0.0429382569f, 0.0414056410f, 0.0398729276f, 0.0383401204f, + 0.0368072229f, 0.0352742389f, 0.0337411719f, 0.0322080254f, 0.0306748032f, + 0.0291415088f, 0.0276081458f, 0.0260747178f, 0.0245412285f, 0.0230076815f, + 0.0214740803f, 0.0199404286f, 0.0184067299f, 0.0168729879f, 0.0153392063f, + 0.0138053885f, 0.0122715383f, 0.0107376592f, 0.0092037548f, 0.0076698287f, + 0.0061358846f, 0.0046019261f, 0.0030679568f, 0.0015339802f +#else +#error Unsupported twiddle table size +#endif +}; diff --git a/dl/sp/src/test/support/float_fft_neon.c b/dl/sp/src/test/support/float_fft_neon.c index 3f0cf16..a10d803 100644 --- a/dl/sp/src/test/support/float_fft_neon.c +++ b/dl/sp/src/test/support/float_fft_neon.c @@ -8,22 +8,37 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include <assert.h> + #include "dl/sp/api/armSP.h" #include "dl/sp/api/omxSP.h" #include "dl/sp/src/test/test_util.h" static const char* message = - "Test forward and inverse floating-point FFT (NEON)\n"; + "Test forward and inverse floating-point FFT" +#if defined(__aarch64__) + " (ARM64)\n" +#else + " (NEON)\n" +#endif + ; const char* UsageMessage() { return message; } +#if defined(__aarch64__) +#define FINISHED_MESSAGE "ARM64 tests finished.\n" +#else +#define FINISHED_MESSAGE "NEON tests finished.\n" +#endif + void FinishedMessage() { - printf("NEON tests finished.\n"); + printf(FINISHED_MESSAGE); } void SetThresholds(struct TestInfo* info) { +#if defined(__arm__) #ifdef BIG_FFT_TABLE info->forward_threshold_ = 138.81; info->inverse_threshold_ = 137.81; @@ -31,6 +46,15 @@ void SetThresholds(struct TestInfo* info) { info->forward_threshold_ = 138.81; info->inverse_threshold_ = 138.81; #endif +#else +#ifdef BIG_FFT_TABLE + info->forward_threshold_ = 138.96; + info->inverse_threshold_ = 138.96; +#else + info->forward_threshold_ = 138.96; + info->inverse_threshold_ = 138.96; +#endif +#endif } OMXResult ForwardFFT(OMX_FC32* x, diff --git a/dl/sp/src/test/support/float_rfft_detect.c b/dl/sp/src/test/support/float_rfft_detect.c index e8b1e54..444e8d6 100644 --- a/dl/sp/src/test/support/float_rfft_detect.c +++ b/dl/sp/src/test/support/float_rfft_detect.c @@ -24,11 +24,11 @@ const char* UsageMessage() { void FinishedMessage() { printf("Tests finished. (Detected %s).\n", - HasArmNeon() ? "NEON" : "Non-NEON"); + omxSP_HasArmNeon() ? "NEON" : "Non-NEON"); } void SetThresholds(struct TestInfo* info) { - if (HasArmNeon()) { + if (omxSP_HasArmNeon()) { info->forward_threshold_ = FLOAT_RFFT_FORWARD_THRESHOLD_NEON; info->inverse_threshold_ = FLOAT_RFFT_INVERSE_THRESHOLD_NEON; } else { diff --git a/dl/sp/src/test/support/float_rfft_mips.c b/dl/sp/src/test/support/float_rfft_mips.c new file mode 100644 index 0000000..4caffcf --- /dev/null +++ b/dl/sp/src/test/support/float_rfft_mips.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "dl/sp/api/omxSP.h" +#include "dl/sp/src/test/test_util.h" +#include "dl/sp/src/test/support/float_rfft_thresholds.h" + +static const char* message = + "Test forward and inverse real floating-point FFT (MIPS)\n"; + +const char* UsageMessage() { + return message; +} + +void FinishedMessage() { + printf("MIPS tests finished.\n"); +} + +void SetThresholds(struct TestInfo* info) { + info->forward_threshold_ = FLOAT_RFFT_FORWARD_THRESHOLD_MIPS; + info->inverse_threshold_ = FLOAT_RFFT_INVERSE_THRESHOLD_MIPS; +} + +OMXResult ForwardRFFT(OMX_F32* x, + OMX_F32* y, + OMXFFTSpec_R_F32* fft_fwd_spec) { + return omxSP_FFTFwd_RToCCS_F32_Sfs(x, y, fft_fwd_spec); +} + +OMXResult InverseRFFT(OMX_F32* y, + OMX_F32* z, + OMXFFTSpec_R_F32* fft_inv_spec) { + return omxSP_FFTInv_CCSToR_F32_Sfs(y, z, fft_inv_spec); +} diff --git a/dl/sp/src/test/support/float_rfft_thresholds.h b/dl/sp/src/test/support/float_rfft_thresholds.h index 2d84eec..84478f7 100644 --- a/dl/sp/src/test/support/float_rfft_thresholds.h +++ b/dl/sp/src/test/support/float_rfft_thresholds.h @@ -23,6 +23,22 @@ #define FLOAT_RFFT_FORWARD_THRESHOLD_ARMV7 (134.95) #define FLOAT_RFFT_INVERSE_THRESHOLD_ARMV7 (142.25) #endif +#elif defined(__aarch64__) +#ifdef BIG_FFT_TABLE +#define FLOAT_RFFT_FORWARD_THRESHOLD_NEON (136.55) +#define FLOAT_RFFT_INVERSE_THRESHOLD_NEON (141.55) +#else +#define FLOAT_RFFT_FORWARD_THRESHOLD_NEON (136.55) +#define FLOAT_RFFT_INVERSE_THRESHOLD_NEON (142.74) +#endif +#elif defined(__mips__) +#ifdef BIG_FFT_TABLE +#define FLOAT_RFFT_FORWARD_THRESHOLD_MIPS (134.65) +#define FLOAT_RFFT_INVERSE_THRESHOLD_MIPS (140.52) +#else +#define FLOAT_RFFT_FORWARD_THRESHOLD_MIPS (137.33) +#define FLOAT_RFFT_INVERSE_THRESHOLD_MIPS (144.88) +#endif #else #ifdef BIG_FFT_TABLE #define FLOAT_RFFT_FORWARD_THRESHOLD_X86 (135.97) diff --git a/dl/sp/src/test/test_fft.gyp b/dl/sp/src/test/test_fft.gyp index 99280b5..c1be018 100644 --- a/dl/sp/src/test/test_fft.gyp +++ b/dl/sp/src/test/test_fft.gyp @@ -128,13 +128,26 @@ }, ], }], + ['target_arch == "arm64"', { + 'targets': [ + { + # Test complex floating-point FFT + 'target_name': 'test_float_fft', + 'type': 'executable', + 'sources': [ + 'test_float_fft.c', + 'support/float_fft_neon.c', + ], + }, + ], + }], ], 'targets': [ # Targets that should be supported by all architectures { # Test utilities 'target_name': 'test_utilities', - 'type' : '<(component)', + 'type' : 'static_library', 'dependencies!' : [ 'test_utilities' ], @@ -143,6 +156,7 @@ 'compare.c', 'gensig.c', 'test_util.c', + 'test_util_fft.c', ], }, { @@ -154,7 +168,7 @@ 'support/float_rfft_thresholds.h', ], 'conditions': [ - ['target_arch == "arm"', { + ['target_arch == "arm" or target_arch == "arm64"', { 'sources': [ 'support/float_rfft_neon.c', ], @@ -164,6 +178,11 @@ 'support/float_rfft_x86.c', ], }], + ['target_arch == "mipsel"', { + 'sources': [ + 'support/float_rfft_mips.c', + ], + }], ], }, { @@ -174,9 +193,9 @@ 'test_fft_time.c', ], 'conditions': [ - ['target_arch == "ia32"', { + ['target_arch == "ia32" or target_arch == "arm64" or target_arch == "mipsel"', { 'defines': [ - # Timing test only for float FFTs on x86 + # Timing test only for float FFTs on x86 and arm64 and MIPSEL. 'FLOAT_ONLY', ], }], @@ -205,6 +224,12 @@ 'test_float_rfft_detect', ], }], + ['target_arch == "arm64"', { + # Supported test programs for ARM64 + 'dependencies': [ + 'test_float_fft', + ], + }], ], 'dependencies' : [ # All architectures must support at least the float rfft test diff --git a/dl/sp/src/test/test_fft_time.c b/dl/sp/src/test/test_fft_time.c index db65134..6154228 100644 --- a/dl/sp/src/test/test_fft_time.c +++ b/dl/sp/src/test/test_fft_time.c @@ -51,7 +51,7 @@ typedef enum { S32, } s16_s32; -#if defined(__arm__) +#if defined(__arm__) || defined(__aarch64__) void TimeOneFloatFFT(int count, int fft_log_size, float signal_value, int signal_type); void TimeFloatFFT(int count, float signal_value, int signal_type); @@ -112,7 +112,7 @@ void TimeFFTUsage(char* prog) { " -T Run just one FFT timing test\n" " -f FFT type:\n" " 0 - Complex Float\n" -#if defined(__arm__) +#if defined(__arm__) || defined(__aarch64__) " 1 - Real Float\n" #endif #ifdef ENABLE_FIXED_POINT_FFT_TESTS @@ -217,7 +217,7 @@ int main(int argc, char* argv[]) { printf("Warning: -f ignored when -T not specified\n"); if (test_mode) { -#if defined(__arm__) +#if defined(__arm__) || defined(__aarch64__) TimeFloatFFT(count, signal_value, signal_type); #endif TimeFloatRFFT(count, signal_value, signal_type); @@ -229,7 +229,7 @@ int main(int argc, char* argv[]) { #endif } else { switch (fft_type) { -#if defined(__arm__) +#if defined(__arm__) || defined(__aarch64__) case 0: TimeOneFloatFFT(count, fft_log_size, signal_value, signal_type); break; @@ -323,7 +323,7 @@ int ComputeCount(int nominal_count, int fft_log_size) { return count; } -#if defined(__arm__) +#if defined(__arm__) || defined(__aarch64__) void TimeOneFloatFFT(int count, int fft_log_size, float signal_value, int signal_type) { struct AlignedPtr* x_aligned; @@ -1061,11 +1061,11 @@ void TimeOneRFFT16(int count, int fft_log_size, float signal_value, if(s16s32 == S32) { PrintResult("Forward RFFT16 (with S32)", - fft_log_size, elapsed_time, count); + fft_log_size, elapsed_time, count); } else { PrintResult("Forward RFFT16 (with S16)", - fft_log_size, elapsed_time, count); + fft_log_size, elapsed_time, count); } } @@ -1124,11 +1124,11 @@ void TimeOneRFFT16(int count, int fft_log_size, float signal_value, if(s16s32 == S32) { PrintResult("Inverse RFFT16 (with S32)", - fft_log_size, elapsed_time, count); + fft_log_size, elapsed_time, count); } else { PrintResult("Inverse RFFT16 (with S16)", - fft_log_size, elapsed_time, count); + fft_log_size, elapsed_time, count); } } diff --git a/dl/sp/src/test/test_float_fft.c b/dl/sp/src/test/test_float_fft.c index 289b197..6aac3a4 100644 --- a/dl/sp/src/test/test_float_fft.c +++ b/dl/sp/src/test/test_float_fft.c @@ -154,7 +154,7 @@ float RunOneForwardTest(int fft_log_size, int signal_type, float signal_value, status = ForwardFFT(x, y, fft_fwd_spec); - if (status) { + if (status != OMX_Sts_NoErr) { fprintf(stderr, "Forward FFT failed: status = %d\n", status); exit(1); } @@ -223,7 +223,7 @@ float RunOneInverseTest(int fft_log_size, int signal_type, float signal_value, status = InverseFFT(y, z, fft_inv_spec); - if (status) { + if (status != OMX_Sts_NoErr) { fprintf(stderr, "Inverse FFT failed: status = %d\n", status); exit(1); } diff --git a/dl/sp/src/test/test_float_rfft.c b/dl/sp/src/test/test_float_rfft.c index a976162..3b37ece 100644 --- a/dl/sp/src/test/test_float_rfft.c +++ b/dl/sp/src/test/test_float_rfft.c @@ -177,7 +177,7 @@ float RunOneForwardTest(int fft_log_size, int signal_type, float signal_value, } status = ForwardRFFT(x, (OMX_F32*) y, fft_fwd_spec); - if (status) { + if (status != OMX_Sts_NoErr) { fprintf(stderr, "Forward FFT failed: status = %d\n", status); exit(1); } @@ -257,7 +257,7 @@ float RunOneInverseTest(int fft_log_size, int signal_type, float signal_value, } status = InverseRFFT((OMX_F32 *) yTrue, z, fft_inv_spec); - if (status) { + if (status != OMX_Sts_NoErr) { fprintf(stderr, "Inverse FFT failed: status = %d\n", status); exit(1); } diff --git a/dl/sp/src/test/test_util.c b/dl/sp/src/test/test_util.c index d21d8c5..a03b27c 100644 --- a/dl/sp/src/test/test_util.c +++ b/dl/sp/src/test/test_util.c @@ -16,30 +16,6 @@ #include "dl/sp/api/armSP.h" #include "dl/sp/src/test/compare.h" -#include "dl/sp/src/test/gensig.h" - -/* - * Test results from running either forward or inverse FFT tests - */ -struct TestResult { - /* Number of tests that failed */ - int failed_count_; - - /* Number of tests run */ - int test_count_; - - /* Number of tests that were expected to fail */ - int expected_failure_count_; - - /* Number of tests that were expected to fail but didn't */ - int unexpected_pass_count_; - - /* Number of tests that unexpectedly failed */ - int unexpected_failure_count_; - - /* The minimum SNR found for all of the tests */ - float min_snr_; -}; /* * Return the program name, fur usage messages and debugging @@ -206,206 +182,6 @@ int IsKnownFailure(int fft_order, int is_inverse_fft, int signal_type, return 0; } -/* - * Run one FFT test - */ -void TestOneFFT(int fft_log_size, - int signal_type, - float signal_value, - const struct TestInfo* info, - const char* message) { - struct SnrResult snr; - - if (info->do_forward_tests_) { - RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr); - printf("Forward %s\n", message); - printf("SNR: real part %10.3f dB\n", snr.real_snr_); - printf(" imag part %10.3f dB\n", snr.imag_snr_); - printf(" complex part %10.3f dB\n", snr.complex_snr_); - } - - if (info->do_inverse_tests_) { - RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr); - printf("Inverse %s\n", message); - if (info->real_only_) { - printf("SNR: real %10.3f dB\n", snr.real_snr_); - } else { - printf("SNR: real part %10.3f dB\n", snr.real_snr_); - printf(" imag part %10.3f dB\n", snr.imag_snr_); - printf(" complex part %10.3f dB\n", snr.complex_snr_); - } - } -} - -/* - * Run a set of tests, printing out the result of each test. - */ -void RunTests(struct TestResult* result, - float (*test_function)(int, int, float, struct SnrResult*), - const char* id, - int is_inverse_test, - const struct TestInfo* info, - float snr_threshold) { - int fft_order; - int signal_type; - float snr; - int tests = 0; - int failures = 0; - int expected_failures = 0; - int unexpected_failures = 0; - int unexpected_passes = 0; - float min_snr = 1e10; - struct SnrResult snrResults; - - for (fft_order = info->min_fft_order_; fft_order <= info->max_fft_order_; - ++fft_order) { - for (signal_type = 0; signal_type < MaxSignalType(info->real_only_); - ++signal_type) { - int known_failure = 0; - int test_failed = 0; - ++tests; - snr = test_function(fft_order, signal_type, 1024.0, &snrResults); - if (snr < min_snr) - min_snr = snr; - known_failure = IsKnownFailure(fft_order, is_inverse_test, - signal_type, info->known_failures_); - if (snr < snr_threshold) { - ++failures; - test_failed = 1; - if (known_failure) { - ++expected_failures; - printf(" *FAILED: %s ", id); - } else { - ++unexpected_failures; - printf("**FAILED: %s ", id); - } - } else { - test_failed = 0; - printf(" PASSED: %s ", id); - } - printf("order %2d signal %d: SNR = %9.3f", - fft_order, signal_type, snr); - if (known_failure) { - if (test_failed) { - printf(" (expected failure)"); - } else { - ++unexpected_passes; - printf(" (**Expected to fail, but passed)"); - } - } - printf("\n"); - } - } - - printf("%sSummary: %d %s tests failed out of %d tests. " - "(Success rate %.2f%%.)\n", - failures ? "**" : "", - failures, - id, - tests, - (100.0 * (tests - failures)) / tests); - if (expected_failures || unexpected_passes || unexpected_failures) { - printf(" (%d expected failures)\n", expected_failures); - printf(" (%d unexpected failures)\n", unexpected_failures); - printf(" (%d unexpected passes)\n", unexpected_passes); - } - - printf(" (Minimum SNR = %.3f dB)\n", min_snr); - - result->failed_count_ = failures; - result->test_count_ = tests; - result->expected_failure_count_ = expected_failures; - result->unexpected_pass_count_ = unexpected_passes; - result->unexpected_failure_count_ = unexpected_failures; - result->min_snr_ = min_snr; -} - -/* - * For all FFT orders and signal types, run the forward FFT. - * runOneForwardTest must be defined to compute the forward FFT and - * return the SNR beween the actual and expected FFT. - * - * Also finds the minium SNR from all of the tests and returns the - * minimum SNR value. - */ -void RunForwardTests(struct TestResult* result, const struct TestInfo* info, - float snr_threshold) { - RunTests(result, RunOneForwardTest, "FwdFFT", 0, info, snr_threshold); -} - -void initializeTestResult(struct TestResult *result) { - result->failed_count_ = 0; - result->test_count_ = 0; - result->expected_failure_count_ = 0; - result->min_snr_ = 1000; -} - -/* - * For all FFT orders and signal types, run the inverse FFT. - * runOneInverseTest must be defined to compute the forward FFT and - * return the SNR beween the actual and expected FFT. - * - * Also finds the minium SNR from all of the tests and returns the - * minimum SNR value. - */ -void RunInverseTests(struct TestResult* result, const struct TestInfo* info, - float snr_threshold) { - RunTests(result, RunOneInverseTest, "InvFFT", 1, info, snr_threshold); -} - -/* - * Run all forward and inverse FFT tests, printing a summary of the - * results. - */ -int RunAllTests(const struct TestInfo* info) { - int failed; - int total; - float min_forward_snr; - float min_inverse_snr; - struct TestResult forward_results; - struct TestResult inverse_results; - - initializeTestResult(&forward_results); - initializeTestResult(&inverse_results); - - if (info->do_forward_tests_) - RunForwardTests(&forward_results, info, info->forward_threshold_); - if (info->do_inverse_tests_) - RunInverseTests(&inverse_results, info, info->inverse_threshold_); - - failed = forward_results.failed_count_ + inverse_results.failed_count_; - total = forward_results.test_count_ + inverse_results.test_count_; - min_forward_snr = forward_results.min_snr_; - min_inverse_snr = inverse_results.min_snr_; - - if (total) { - printf("%sTotal: %d tests failed out of %d tests. " - "(Success rate = %.2f%%.)\n", - failed ? "**" : "", - failed, - total, - (100.0 * (total - failed)) / total); - if (forward_results.expected_failure_count_ - + inverse_results.expected_failure_count_) { - printf(" (%d expected failures)\n", - forward_results.expected_failure_count_ - + inverse_results.expected_failure_count_); - printf(" (%d unexpected failures)\n", - forward_results.unexpected_failure_count_ - + inverse_results.unexpected_failure_count_); - printf(" (%d unexpected passes)\n", - forward_results.unexpected_pass_count_ - + inverse_results.unexpected_pass_count_); - } - printf(" Min forward SNR = %.3f dB, min inverse SNR = %.3f dB\n", - min_forward_snr, - min_inverse_snr); - } else { - printf("No tests run\n"); - } - - return failed; -} /* * Print the contents of an array to stdout, one element per line. diff --git a/dl/sp/src/test/test_util_fft.c b/dl/sp/src/test/test_util_fft.c new file mode 100644 index 0000000..3deb041 --- /dev/null +++ b/dl/sp/src/test/test_util_fft.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include "dl/sp/src/test/test_util.h" + +#include "dl/sp/src/test/compare.h" + +/* + * Test results from running either forward or inverse FFT tests + */ +struct TestResult { + /* Number of tests that failed */ + int failed_count_; + + /* Number of tests run */ + int test_count_; + + /* Number of tests that were expected to fail */ + int expected_failure_count_; + + /* Number of tests that were expected to fail but didn't */ + int unexpected_pass_count_; + + /* Number of tests that unexpectedly failed */ + int unexpected_failure_count_; + + /* The minimum SNR found for all of the tests */ + float min_snr_; +}; + +/* + * Run one FFT test + */ +void TestOneFFT(int fft_log_size, + int signal_type, + float signal_value, + const struct TestInfo* info, + const char* message) { + struct SnrResult snr; + + if (info->do_forward_tests_) { + RunOneForwardTest(fft_log_size, signal_type, signal_value, &snr); + printf("Forward %s\n", message); + printf("SNR: real part %10.3f dB\n", snr.real_snr_); + printf(" imag part %10.3f dB\n", snr.imag_snr_); + printf(" complex part %10.3f dB\n", snr.complex_snr_); + } + + if (info->do_inverse_tests_) { + RunOneInverseTest(fft_log_size, signal_type, signal_value, &snr); + printf("Inverse %s\n", message); + if (info->real_only_) { + printf("SNR: real %10.3f dB\n", snr.real_snr_); + } else { + printf("SNR: real part %10.3f dB\n", snr.real_snr_); + printf(" imag part %10.3f dB\n", snr.imag_snr_); + printf(" complex part %10.3f dB\n", snr.complex_snr_); + } + } +} + +/* + * Run a set of tests, printing out the result of each test. + */ +void RunTests(struct TestResult* result, + float (*test_function)(int, int, float, struct SnrResult*), + const char* id, + int is_inverse_test, + const struct TestInfo* info, + float snr_threshold) { + int fft_order; + int signal_type; + float snr; + int tests = 0; + int failures = 0; + int expected_failures = 0; + int unexpected_failures = 0; + int unexpected_passes = 0; + float min_snr = 1e10; + struct SnrResult snrResults; + + for (fft_order = info->min_fft_order_; fft_order <= info->max_fft_order_; + ++fft_order) { + for (signal_type = 0; signal_type < MaxSignalType(info->real_only_); + ++signal_type) { + int known_failure = 0; + int test_failed = 0; + ++tests; + snr = test_function(fft_order, signal_type, 1024.0, &snrResults); + if (snr < min_snr) + min_snr = snr; + known_failure = IsKnownFailure(fft_order, is_inverse_test, + signal_type, info->known_failures_); + if (snr < snr_threshold) { + ++failures; + test_failed = 1; + if (known_failure) { + ++expected_failures; + printf(" *FAILED: %s ", id); + } else { + ++unexpected_failures; + printf("**FAILED: %s ", id); + } + } else { + test_failed = 0; + printf(" PASSED: %s ", id); + } + printf("order %2d signal %d: SNR = %9.3f", + fft_order, signal_type, snr); + if (known_failure) { + if (test_failed) { + printf(" (expected failure)"); + } else { + ++unexpected_passes; + printf(" (**Expected to fail, but passed)"); + } + } + printf("\n"); + } + } + + printf("%sSummary: %d %s tests failed out of %d tests. " + "(Success rate %.2f%%.)\n", + failures ? "**" : "", + failures, + id, + tests, + (100.0 * (tests - failures)) / tests); + if (expected_failures || unexpected_passes || unexpected_failures) { + printf(" (%d expected failures)\n", expected_failures); + printf(" (%d unexpected failures)\n", unexpected_failures); + printf(" (%d unexpected passes)\n", unexpected_passes); + } + + printf(" (Minimum SNR = %.3f dB)\n", min_snr); + + result->failed_count_ = failures; + result->test_count_ = tests; + result->expected_failure_count_ = expected_failures; + result->unexpected_pass_count_ = unexpected_passes; + result->unexpected_failure_count_ = unexpected_failures; + result->min_snr_ = min_snr; +} + +/* + * For all FFT orders and signal types, run the forward FFT. + * runOneForwardTest must be defined to compute the forward FFT and + * return the SNR beween the actual and expected FFT. + * + * Also finds the minium SNR from all of the tests and returns the + * minimum SNR value. + */ +void RunForwardTests(struct TestResult* result, const struct TestInfo* info, + float snr_threshold) { + RunTests(result, RunOneForwardTest, "FwdFFT", 0, info, snr_threshold); +} + +void initializeTestResult(struct TestResult *result) { + result->failed_count_ = 0; + result->test_count_ = 0; + result->expected_failure_count_ = 0; + result->min_snr_ = 1000; +} + +/* + * For all FFT orders and signal types, run the inverse FFT. + * runOneInverseTest must be defined to compute the forward FFT and + * return the SNR beween the actual and expected FFT. + * + * Also finds the minium SNR from all of the tests and returns the + * minimum SNR value. + */ +void RunInverseTests(struct TestResult* result, const struct TestInfo* info, + float snr_threshold) { + RunTests(result, RunOneInverseTest, "InvFFT", 1, info, snr_threshold); +} + +/* + * Run all forward and inverse FFT tests, printing a summary of the + * results. + */ +int RunAllTests(const struct TestInfo* info) { + int failed; + int total; + float min_forward_snr; + float min_inverse_snr; + struct TestResult forward_results; + struct TestResult inverse_results; + + initializeTestResult(&forward_results); + initializeTestResult(&inverse_results); + + if (info->do_forward_tests_) + RunForwardTests(&forward_results, info, info->forward_threshold_); + if (info->do_inverse_tests_) + RunInverseTests(&inverse_results, info, info->inverse_threshold_); + + failed = forward_results.failed_count_ + inverse_results.failed_count_; + total = forward_results.test_count_ + inverse_results.test_count_; + min_forward_snr = forward_results.min_snr_; + min_inverse_snr = inverse_results.min_snr_; + + if (total) { + printf("%sTotal: %d tests failed out of %d tests. " + "(Success rate = %.2f%%.)\n", + failed ? "**" : "", + failed, + total, + (100.0 * (total - failed)) / total); + if (forward_results.expected_failure_count_ + + inverse_results.expected_failure_count_) { + printf(" (%d expected failures)\n", + forward_results.expected_failure_count_ + + inverse_results.expected_failure_count_); + printf(" (%d unexpected failures)\n", + forward_results.unexpected_failure_count_ + + inverse_results.unexpected_failure_count_); + printf(" (%d unexpected passes)\n", + forward_results.unexpected_pass_count_ + + inverse_results.unexpected_pass_count_); + } + printf(" Min forward SNR = %.3f dB, min inverse SNR = %.3f dB\n", + min_forward_snr, + min_inverse_snr); + } else { + printf("No tests run\n"); + } + + return failed; +} |