summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Gevaerts <frank@gevaerts.be>2010-02-10 19:44:11 +0000
committerFrank Gevaerts <frank@gevaerts.be>2010-02-10 19:44:11 +0000
commit43264a946f0222e49ac2c10da7d00b36efc3f40e (patch)
treed0ef77e8280819bfc23f9ef101e1374011ad6e1b
parentfa4ab10bbbd5b3588bc0e7057b338d1068939fda (diff)
downloadrockbox-43264a946f0222e49ac2c10da7d00b36efc3f40e.tar.gz
rockbox-43264a946f0222e49ac2c10da7d00b36efc3f40e.tar.bz2
rockbox-43264a946f0222e49ac2c10da7d00b36efc3f40e.zip
New plugin: FFT, A frequency analyzer plugin
There is some more work needed: - Keymaps are definitely not perfect, touchscreen targets are disabled due to no keymap - There is no manual yet Author: Delyan Kratunov Flyspray: FS#10065 git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24587 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugin.c1
-rw-r--r--apps/plugin.h1
-rw-r--r--apps/plugins/CATEGORIES1
-rw-r--r--apps/plugins/SUBDIRS3
-rw-r--r--apps/plugins/bitmaps/native/SOURCES5
-rw-r--r--apps/plugins/bitmaps/native/fft_colors.16.bmpbin0 -> 822 bytes
-rw-r--r--apps/plugins/fft/SOURCES4
-rw-r--r--apps/plugins/fft/_kiss_fft_guts.h152
-rw-r--r--apps/plugins/fft/const.h2650
-rw-r--r--apps/plugins/fft/fft.c1165
-rw-r--r--apps/plugins/fft/fft.make27
-rw-r--r--apps/plugins/fft/kiss_fft.c428
-rw-r--r--apps/plugins/fft/kiss_fft.h119
-rw-r--r--apps/plugins/fft/kiss_fftr.c153
-rw-r--r--apps/plugins/fft/kiss_fftr.h54
-rw-r--r--apps/plugins/fft/math.c13
-rw-r--r--apps/plugins/fft/math.h28
-rw-r--r--firmware/export/pcm.h1
-rw-r--r--firmware/pcm.c5
19 files changed, 4810 insertions, 0 deletions
diff --git a/apps/plugin.c b/apps/plugin.c
index 47f2465631..a1ffa3abe1 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -448,6 +448,7 @@ static const struct plugin_api rockbox_api = {
pcm_play_pause,
pcm_get_bytes_waiting,
pcm_calculate_peaks,
+ pcm_get_peak_buffer,
pcm_play_lock,
pcm_play_unlock,
#ifdef HAVE_RECORDING
diff --git a/apps/plugin.h b/apps/plugin.h
index a7a6203e53..a87d873713 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -580,6 +580,7 @@ struct plugin_api {
void (*pcm_play_pause)(bool play);
size_t (*pcm_get_bytes_waiting)(void);
void (*pcm_calculate_peaks)(int *left, int *right);
+ const void* (*pcm_get_peak_buffer)(int *count);
void (*pcm_play_lock)(void);
void (*pcm_play_unlock)(void);
#ifdef HAVE_RECORDING
diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index cf6e2663fa..218055e311 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -24,6 +24,7 @@ dict,apps
disktidy,apps
doom,games
euroconverter,apps
+fft,demos
fire,demos
fireworks,demos
firmware_flash,apps
diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS
index 99d3060459..a0d68af510 100644
--- a/apps/plugins/SUBDIRS
+++ b/apps/plugins/SUBDIRS
@@ -19,6 +19,9 @@ rockboy
#ifdef HAVE_TAGCACHE
pictureflow
#endif
+#if CONFIG_CODEC == SWCODEC && !defined(HAVE_TOUCHSCREEN)
+fft
+#endif
chessbox
fractals
imageviewer
diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES
index 63f229272d..ed8c3c7cc8 100644
--- a/apps/plugins/bitmaps/native/SOURCES
+++ b/apps/plugins/bitmaps/native/SOURCES
@@ -261,6 +261,11 @@ clock_logo.112x64x1.bmp
clock_messages.112x64x1.bmp
#endif
+/* FFT only needs a bitmap with colors mapping to amplitude */
+#ifdef HAVE_LCD_COLOR
+fft_colors.16.bmp
+#endif
+
/* Flipit */
#ifdef HAVE_LCD_COLOR
#if LCD_WIDTH >= 480
diff --git a/apps/plugins/bitmaps/native/fft_colors.16.bmp b/apps/plugins/bitmaps/native/fft_colors.16.bmp
new file mode 100644
index 0000000000..20f6718bf8
--- /dev/null
+++ b/apps/plugins/bitmaps/native/fft_colors.16.bmp
Binary files differ
diff --git a/apps/plugins/fft/SOURCES b/apps/plugins/fft/SOURCES
new file mode 100644
index 0000000000..07fb013eaa
--- /dev/null
+++ b/apps/plugins/fft/SOURCES
@@ -0,0 +1,4 @@
+kiss_fft.c
+kiss_fftr.c
+fft.c
+math.c
diff --git a/apps/plugins/fft/_kiss_fft_guts.h b/apps/plugins/fft/_kiss_fft_guts.h
new file mode 100644
index 0000000000..e9ce9e9a9c
--- /dev/null
+++ b/apps/plugins/fft/_kiss_fft_guts.h
@@ -0,0 +1,152 @@
+/*
+Copyright (c) 2003-2004, Mark Borgerding
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+/* kiss_fft.h
+ defines kiss_fft_scalar as either short or a float type
+ and defines
+ typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
+#include "kiss_fft.h"
+#include "math.h"
+#include <limits.h>
+
+#define MAXFACTORS 32
+/* e.g. an fft of length 128 has 4 factors
+ as far as kissfft is concerned
+ 4*4*4*2
+ */
+
+struct kiss_fft_state{
+ int nfft;
+ int inverse;
+ int factors[2*MAXFACTORS];
+ kiss_fft_cpx twiddles[1];
+};
+
+/*
+ Explanation of macros dealing with complex math:
+
+ C_MUL(m,a,b) : m = a*b
+ C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
+ C_SUB( res, a,b) : res = a - b
+ C_SUBFROM( res , a) : res -= a
+ C_ADDTO( res , a) : res += a
+ * */
+#ifdef FIXED_POINT
+#if (FIXED_POINT==32)
+# define FRACBITS 31
+# define SAMPPROD int64_t
+#define SAMP_MAX 2147483647
+#else
+# define FRACBITS 15
+# define SAMPPROD int32_t
+#define SAMP_MAX 32767
+#endif
+
+#define SAMP_MIN -SAMP_MAX
+
+#if defined(CHECK_OVERFLOW)
+# define CHECK_OVERFLOW_OP(a,op,b) \
+ if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
+ fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); }
+#endif
+
+
+# define smul(a,b) ( (SAMPPROD)(a)*(b) )
+# define sround( x ) (kiss_fft_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS )
+
+# define S_MUL(a,b) sround( smul(a,b) )
+
+# define C_MUL(m,a,b) \
+ do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \
+ (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0)
+
+# define DIVSCALAR(x,k) \
+ (x) = sround( smul( x, SAMP_MAX/k ) )
+
+# define C_FIXDIV(c,div) \
+ do { DIVSCALAR( (c).r , div); \
+ DIVSCALAR( (c).i , div); }while (0)
+
+# define C_MULBYSCALAR( c, s ) \
+ do{ (c).r = sround( smul( (c).r , s ) ) ;\
+ (c).i = sround( smul( (c).i , s ) ) ; }while(0)
+
+#else /* not FIXED_POINT*/
+
+# define S_MUL(a,b) ( (a)*(b) )
+#define C_MUL(m,a,b) \
+ do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
+ (m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
+# define C_FIXDIV(c,div) /* NOOP */
+# define C_MULBYSCALAR( c, s ) \
+ do{ (c).r *= (s);\
+ (c).i *= (s); }while(0)
+#endif
+
+#ifndef CHECK_OVERFLOW_OP
+# define CHECK_OVERFLOW_OP(a,op,b) /* noop */
+#endif
+
+#define C_ADD( res, a,b)\
+ do { \
+ CHECK_OVERFLOW_OP((a).r,+,(b).r)\
+ CHECK_OVERFLOW_OP((a).i,+,(b).i)\
+ (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
+ }while(0)
+#define C_SUB( res, a,b)\
+ do { \
+ CHECK_OVERFLOW_OP((a).r,-,(b).r)\
+ CHECK_OVERFLOW_OP((a).i,-,(b).i)\
+ (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
+ }while(0)
+#define C_ADDTO( res , a)\
+ do { \
+ CHECK_OVERFLOW_OP((res).r,+,(a).r)\
+ CHECK_OVERFLOW_OP((res).i,+,(a).i)\
+ (res).r += (a).r; (res).i += (a).i;\
+ }while(0)
+
+#define C_SUBFROM( res , a)\
+ do {\
+ CHECK_OVERFLOW_OP((res).r,-,(a).r)\
+ CHECK_OVERFLOW_OP((res).i,-,(a).i)\
+ (res).r -= (a).r; (res).i -= (a).i; \
+ }while(0)
+
+
+#ifdef FIXED_POINT
+# define HALF_OF(x) ((x)>>1)
+#else
+# define HALF_OF(x) ((x)*.5)
+#endif
+
+#define kf_cexp(x, k, n) \
+ do{ \
+ int32_t div = Q_DIV( (k) << 16, (n) << 16, 16 ); \
+ long cos, sin = fp_sincos(div << 16, &cos); \
+ (x)->r = ( Q_MUL(SAMP_MAX << 16, cos >> 15, 16) ) >> 16; \
+ (x)->i = ( Q_MUL(SAMP_MAX << 16, -1*(sin >> 15), 16) ) >> 16; \
+ }while(0)
+
+#define kf_cexp_round(x, k, n) \
+ do{ \
+ int32_t div = Q_DIV( (k) << 16, (n) << 16, 16 ) + (1 << 15); \
+ long cos, sin = fp_sincos(div << 16, &cos); \
+ (x)->r = ( Q_MUL(SAMP_MAX << 16, cos >> 15, 16) ) >> 16; \
+ (x)->i = ( Q_MUL(SAMP_MAX << 16, -1*(sin >> 15), 16) ) >> 16; \
+ }while(0)
+
+/* a debugging function */
+#define pcpx(c)\
+ fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) )
diff --git a/apps/plugins/fft/const.h b/apps/plugins/fft/const.h
new file mode 100644
index 0000000000..6f8cbe9f6e
--- /dev/null
+++ b/apps/plugins/fft/const.h
@@ -0,0 +1,2650 @@
+const int32_t hamming_8192 [] = {2514,2514,2514,2514,2514,2514,2514,2514,2514,2514,2514,2514,
+2514,2514,2514,2515,2515,2515,2515,2515,2515,2516,2516,2516,
+2516,2517,2517,2517,2517,2518,2518,2518,2518,2519,2519,2519,
+2520,2520,2520,2520,2521,2521,2522,2522,2522,2523,2523,2524,
+2524,2525,2525,2526,2526,2526,2527,2527,2528,2528,2529,2529,
+2530,2530,2531,2532,2532,2532,2533,2534,2534,2535,2536,2536,
+2537,2538,2538,2539,2539,2540,2541,2542,2542,2543,2544,2544,
+2545,2546,2547,2547,2548,2549,2550,2550,2551,2552,2553,2554,
+2555,2556,2556,2557,2558,2559,2560,2561,2562,2563,2564,2565,
+2566,2567,2568,2568,2569,2570,2572,2573,2574,2574,2576,2577,
+2578,2579,2580,2581,2582,2583,2584,2586,2586,2588,2589,2590,
+2591,2592,2593,2595,2596,2597,2598,2600,2601,2602,2604,2604,
+2606,2607,2609,2610,2611,2612,2614,2615,2616,2618,2619,2621,
+2622,2623,2625,2626,2628,2629,2630,2632,2633,2635,2636,2638,
+2639,2640,2642,2644,2645,2647,2648,2650,2652,2653,2654,2656,
+2658,2659,2661,2663,2664,2666,2667,2669,2671,2672,2674,2676,
+2677,2679,2681,2682,2684,2686,2688,2689,2691,2693,2695,2697,
+2699,2700,2702,2704,2706,2708,2710,2712,2713,2715,2717,2719,
+2721,2723,2724,2727,2729,2730,2732,2735,2736,2738,2741,2742,
+2744,2747,2748,2750,2753,2754,2757,2759,2761,2763,2765,2767,
+2769,2772,2773,2776,2778,2780,2782,2784,2787,2789,2791,2793,
+2796,2798,2800,2802,2804,2807,2809,2811,2814,2816,2818,2820,
+2823,2825,2827,2830,2832,2834,2837,2839,2842,2844,2846,2849,
+2851,2854,2856,2859,2861,2864,2866,2869,2871,2874,2876,2879,
+2881,2884,2887,2889,2892,2894,2897,2899,2902,2905,2907,2910,
+2912,2915,2918,2920,2923,2926,2929,2931,2934,2936,2939,2942,
+2945,2947,2950,2953,2956,2959,2961,2964,2967,2970,2973,2976,
+2978,2981,2984,2987,2990,2993,2996,2999,3001,3004,3007,3010,
+3013,3016,3019,3022,3025,3028,3031,3034,3037,3040,3043,3046,
+3049,3052,3055,3059,3061,3065,3068,3071,3074,3077,3080,3084,
+3087,3090,3093,3096,3099,3103,3106,3109,3112,3115,3119,3122,
+3125,3128,3132,3135,3139,3142,3145,3148,3151,3155,3158,3162,
+3165,3169,3172,3175,3179,3182,3186,3189,3192,3196,3199,3203,
+3206,3210,3213,3217,3220,3224,3227,3230,3234,3238,3241,3245,
+3248,3252,3255,3259,3263,3266,3270,3273,3277,3281,3284,3288,
+3292,3296,3299,3303,3307,3310,3314,3318,3321,3325,3329,3333,
+3337,3340,3344,3348,3352,3356,3359,3363,3367,3371,3375,3379,
+3382,3386,3390,3394,3398,3402,3406,3410,3414,3418,3422,3426,
+3429,3434,3438,3441,3446,3450,3453,3458,3462,3466,3470,3474,
+3478,3482,3486,3490,3494,3498,3502,3506,3511,3515,3519,3523,
+3527,3531,3536,3540,3544,3548,3553,3557,3561,3565,3570,3574,
+3578,3582,3587,3591,3595,3600,3604,3608,3613,3617,3621,3626,
+3630,3634,3639,3643,3647,3652,3657,3661,3665,3669,3674,3679,
+3683,3687,3692,3697,3701,3705,3710,3715,3719,3723,3728,3733,
+3737,3742,3747,3751,3756,3760,3765,3770,3774,3779,3783,3788,
+3793,3797,3802,3807,3812,3816,3821,3825,3831,3835,3840,3844,
+3849,3854,3859,3864,3868,3873,3878,3883,3888,3892,3897,3902,
+3907,3912,3917,3922,3927,3932,3936,3941,3946,3951,3956,3961,
+3966,3971,3976,3981,3986,3991,3996,4001,4006,4011,4016,4021,
+4026,4031,4036,4042,4047,4052,4057,4062,4067,4072,4077,4082,
+4087,4093,4098,4103,4108,4114,4119,4124,4129,4134,4139,4144,
+4150,4155,4160,4166,4171,4176,4181,4187,4192,4198,4203,4208,
+4213,4219,4224,4229,4235,4240,4246,4251,4256,4262,4267,4273,
+4278,4283,4289,4295,4300,4306,4311,4316,4322,4327,4333,4338,
+4344,4349,4355,4361,4366,4372,4377,4383,4388,4394,4400,4405,
+4411,4416,4422,4428,4433,4439,4445,4451,4456,4462,4468,4473,
+4479,4485,4490,4496,4502,4508,4513,4519,4525,4531,4536,4542,
+4548,4554,4560,4565,4571,4577,4583,4589,4595,4601,4607,4613,
+4619,4624,4630,4636,4642,4648,4654,4660,4666,4672,4678,4684,
+4690,4696,4702,4708,4714,4720,4726,4732,4738,4744,4750,4756,
+4762,4768,4775,4781,4787,4793,4799,4805,4811,4818,4824,4830,
+4836,4842,4848,4854,4860,4867,4873,4879,4885,4892,4898,4904,
+4910,4917,4923,4929,4936,4942,4948,4955,4961,4967,4974,4980,
+4987,4993,4999,5005,5012,5018,5024,5031,5037,5044,5050,5057,
+5063,5070,5076,5083,5089,5095,5102,5108,5115,5121,5128,5134,
+5141,5148,5154,5161,5167,5174,5180,5187,5193,5200,5207,5213,
+5220,5227,5233,5240,5246,5253,5260,5266,5273,5280,5287,5293,
+5300,5306,5313,5320,5327,5334,5340,5347,5354,5360,5367,5374,
+5381,5388,5395,5402,5408,5415,5422,5429,5436,5443,5449,5456,
+5463,5470,5477,5484,5491,5498,5504,5511,5518,5525,5532,5539,
+5546,5553,5560,5567,5574,5581,5588,5595,5602,5609,5616,5623,
+5630,5637,5644,5651,5659,5666,5672,5680,5687,5694,5701,5709,
+5715,5722,5730,5737,5744,5751,5758,5766,5773,5780,5787,5794,
+5802,5809,5816,5823,5830,5838,5845,5852,5859,5867,5874,5882,
+5889,5896,5903,5911,5918,5925,5933,5940,5947,5955,5962,5969,
+5977,5984,5991,5999,6007,6014,6021,6029,6036,6044,6051,6058,
+6066,6074,6081,6088,6096,6104,6111,6118,6126,6134,6141,6148,
+6156,6164,6171,6179,6186,6194,6202,6209,6217,6225,6232,6240,
+6247,6255,6262,6270,6278,6286,6293,6301,6309,6316,6324,6332,
+6340,6347,6355,6363,6370,6378,6386,6394,6401,6409,6417,6425,
+6432,6440,6448,6456,6464,6472,6479,6487,6495,6503,6511,6519,
+6527,6534,6542,6550,6558,6566,6574,6581,6589,6598,6605,6613,
+6621,6629,6637,6645,6653,6661,6669,6677,6685,6693,6701,6709,
+6717,6725,6733,6741,6749,6757,6765,6774,6781,6790,6798,6806,
+6814,6822,6830,6838,6846,6854,6863,6871,6879,6887,6895,6903,
+6912,6920,6928,6936,6945,6954,6962,6970,6978,6986,6995,7003,
+7011,7020,7028,7036,7044,7052,7061,7069,7077,7086,7094,7102,
+7111,7119,7128,7136,7144,7153,7161,7169,7177,7186,7195,7203,
+7211,7219,7228,7237,7245,7253,7261,7270,7279,7287,7296,7304,
+7312,7321,7329,7338,7346,7355,7363,7372,7381,7389,7398,7406,
+7415,7423,7432,7440,7449,7457,7466,7475,7483,7492,7500,7509,
+7518,7526,7535,7544,7552,7561,7569,7578,7587,7595,7604,7613,
+7622,7630,7639,7647,7656,7665,7674,7682,7691,7700,7709,7718,
+7726,7735,7744,7753,7761,7770,7779,7788,7797,7805,7814,7823,
+7832,7841,7850,7858,7867,7876,7885,7894,7903,7911,7920,7929,
+7938,7947,7956,7965,7974,7983,7992,8001,8010,8019,8027,8037,
+8045,8055,8063,8072,8081,8090,8099,8108,8117,8126,8135,8145,
+8153,8163,8171,8181,8190,8199,8208,8217,8226,8235,8244,8253,
+8262,8272,8280,8290,8299,8308,8317,8326,8335,8344,8354,8363,
+8372,8381,8390,8399,8409,8418,8427,8436,8446,8455,8464,8473,
+8482,8492,8501,8510,8519,8529,8538,8547,8556,8566,8575,8584,
+8593,8603,8612,8621,8631,8640,8650,8659,8668,8677,8687,8696,
+8705,8715,8724,8734,8743,8753,8762,8771,8781,8790,8799,8809,
+8818,8828,8837,8846,8856,8865,8875,8884,8894,8903,8913,8922,
+8932,8941,8951,8960,8970,8979,8988,8998,9008,9017,9027,9036,
+9046,9055,9065,9074,9084,9094,9103,9113,9122,9132,9142,9151,
+9161,9170,9180,9190,9199,9209,9218,9228,9238,9247,9257,9267,
+9277,9286,9296,9306,9315,9325,9335,9344,9354,9364,9373,9383,
+9393,9403,9412,9422,9432,9441,9451,9461,9471,9481,9490,9500,
+9510,9520,9529,9539,9549,9559,9569,9578,9588,9598,9608,9618,
+9628,9638,9647,9657,9667,9677,9687,9697,9706,9716,9726,9736,
+9746,9756,9766,9776,9786,9795,9806,9815,9825,9835,9845,9855,
+9865,9875,9885,9895,9905,9915,9925,9935,9945,9955,9965,9975,
+9985,9995,10005,10015,10025,10035,10045,10055,10065,10075,10085,10095,
+10105,10115,10125,10136,10146,10155,10166,10176,10186,10196,10206,10216,
+10226,10236,10246,10257,10267,10277,10287,10297,10307,10318,10328,10338,
+10348,10358,10368,10378,10389,10399,10409,10419,10430,10440,10450,10460,
+10470,10480,10491,10501,10511,10522,10532,10542,10552,10562,10573,10583,
+10593,10603,10614,10624,10634,10644,10655,10665,10675,10686,10696,10706,
+10717,10727,10737,10748,10758,10769,10779,10789,10799,10810,10820,10830,
+10841,10851,10861,10872,10882,10893,10903,10913,10924,10934,10944,10955,
+10965,10976,10986,10997,11007,11017,11028,11039,11049,11059,11070,11080,
+11091,11101,11112,11122,11132,11143,11154,11164,11174,11185,11196,11206,
+11216,11227,11238,11248,11258,11269,11280,11290,11300,11311,11322,11332,
+11343,11353,11364,11374,11385,11395,11406,11417,11427,11438,11449,11459,
+11470,11480,11491,11501,11512,11522,11533,11544,11554,11565,11575,11586,
+11597,11608,11618,11629,11640,11650,11661,11672,11682,11693,11703,11714,
+11725,11736,11746,11757,11768,11778,11789,11800,11810,11821,11832,11842,
+11853,11864,11875,11885,11896,11907,11918,11928,11939,11950,11960,11972,
+11982,11993,12003,12015,12025,12036,12047,12057,12068,12079,12090,12101,
+12111,12122,12133,12144,12155,12165,12177,12187,12198,12209,12219,12231,
+12241,12252,12263,12274,12285,12296,12306,12317,12328,12339,12350,12361,
+12371,12382,12394,12404,12415,12426,12437,12448,12459,12470,12480,12491,
+12502,12513,12524,12535,12546,12557,12568,12579,12590,12601,12611,12622,
+12634,12644,12655,12666,12677,12688,12699,12710,12721,12732,12743,12754,
+12765,12776,12787,12798,12809,12820,12831,12842,12853,12864,12875,12886,
+12897,12908,12919,12930,12941,12952,12963,12974,12985,12996,13007,13019,
+13030,13041,13051,13062,13074,13085,13096,13107,13118,13129,13140,13151,
+13162,13173,13184,13195,13206,13218,13229,13240,13251,13262,13273,13284,
+13296,13307,13318,13329,13340,13351,13362,13373,13384,13396,13407,13418,
+13429,13440,13451,13462,13474,13485,13496,13507,13518,13529,13541,13552,
+13563,13574,13585,13597,13608,13619,13630,13641,13652,13663,13675,13686,
+13697,13708,13719,13731,13742,13753,13765,13776,13787,13798,13809,13820,
+13832,13843,13854,13865,13877,13888,13899,13910,13922,13933,13944,13955,
+13967,13978,13989,14000,14012,14023,14034,14045,14057,14068,14079,14090,
+14102,14113,14124,14136,14147,14158,14169,14181,14192,14204,14215,14226,
+14237,14249,14260,14271,14283,14294,14305,14317,14328,14339,14350,14362,
+14373,14385,14396,14407,14418,14430,14441,14452,14464,14475,14487,14498,
+14509,14521,14532,14543,14554,14566,14578,14589,14600,14611,14623,14634,
+14645,14657,14668,14680,14691,14703,14714,14725,14736,14748,14759,14771,
+14782,14794,14805,14816,14828,14839,14850,14862,14873,14885,14896,14908,
+14919,14930,14942,14953,14965,14976,14987,14999,15010,15022,15033,15045,
+15056,15067,15079,15090,15102,15113,15125,15136,15148,15159,15170,15182,
+15193,15205,15216,15228,15239,15251,15262,15274,15285,15296,15308,15319,
+15331,15342,15354,15365,15377,15388,15400,15411,15423,15434,15445,15457,
+15468,15480,15492,15503,15515,15526,15537,15549,15560,15572,15583,15595,
+15607,15618,15629,15641,15652,15664,15675,15687,15698,15710,15721,15733,
+15745,15756,15768,15779,15790,15802,15813,15825,15836,15848,15859,15871,
+15883,15894,15906,15917,15929,15940,15952,15963,15975,15986,15998,16010,
+16021,16033,16044,16056,16067,16079,16090,16102,16113,16125,16136,16148,
+16160,16171,16183,16194,16206,16217,16229,16240,16252,16263,16275,16287,
+16298,16310,16321,16333,16344,16356,16367,16379,16390,16402,16413,16425,
+16437,16449,16460,16472,16483,16495,16506,16518,16529,16541,16552,16564,
+16575,16587,16599,16611,16622,16634,16645,16657,16668,16680,16691,16703,
+16714,16726,16738,16750,16761,16773,16784,16796,16807,16819,16830,16842,
+16853,16865,16877,16888,16900,16912,16923,16935,16946,16958,16969,16981,
+16993,17004,17016,17027,17039,17051,17062,17074,17086,17097,17109,17120,
+17132,17143,17155,17166,17178,17190,17201,17213,17225,17236,17248,17259,
+17271,17283,17294,17306,17317,17329,17340,17352,17364,17376,17387,17399,
+17410,17422,17433,17445,17457,17468,17480,17491,17503,17514,17526,17538,
+17550,17561,17573,17584,17596,17607,17619,17631,17644,17655,17667,17678,
+17690,17701,17713,17725,17737,17748,17760,17771,17783,17795,17806,17818,
+17829,17841,17852,17864,17875,17887,17899,17911,17922,17934,17945,17957,
+17968,17980,17992,18003,18015,18026,18038,18050,18061,18073,18085,18096,
+18108,18119,18131,18142,18154,18166,18177,18189,18200,18212,18224,18235,
+18247,18258,18270,18282,18293,18305,18316,18328,18339,18351,18363,18375,
+18386,18398,18409,18421,18432,18444,18455,18467,18478,18490,18502,18513,
+18525,18537,18548,18560,18571,18583,18594,18606,18617,18629,18641,18652,
+18664,18675,18687,18699,18710,18722,18733,18745,18756,18768,18779,18791,
+18803,18814,18826,18838,18849,18861,18872,18884,18895,18907,18918,18930,
+18941,18953,18964,18976,18988,18999,19011,19022,19034,19045,19057,19068,
+19080,19092,19103,19115,19127,19138,19150,19161,19173,19184,19196,19207,
+19219,19230,19242,19253,19265,19277,19288,19300,19311,19322,19334,19345,
+19357,19368,19380,19391,19403,19415,19426,19438,19449,19461,19472,19484,
+19495,19507,19518,19530,19542,19553,19565,19576,19587,19599,19610,19622,
+19633,19645,19656,19668,19680,19691,19702,19714,19725,19737,19748,19760,
+19771,19783,19795,19806,19817,19829,19840,19852,19863,19875,19886,19897,
+19909,19921,19932,19944,19955,19966,19978,19989,20001,20012,20024,20035,
+20047,20058,20070,20081,20092,20104,20115,20127,20138,20150,20161,20173,
+20184,20195,20207,20218,20230,20241,20252,20264,20276,20287,20298,20310,
+20321,20332,20344,20355,20367,20378,20390,20401,20413,20424,20435,20447,
+20458,20469,20481,20492,20504,20515,20526,20538,20549,20560,20572,20583,
+20595,20606,20618,20629,20640,20652,20663,20674,20685,20697,20709,20720,
+20731,20742,20754,20765,20776,20788,20799,20811,20822,20833,20845,20856,
+20867,20878,20890,20901,20913,20924,20935,20947,20958,20969,20980,20992,
+21003,21015,21026,21037,21048,21060,21071,21082,21094,21105,21116,21127,
+21139,21150,21161,21173,21184,21195,21207,21218,21229,21240,21251,21263,
+21274,21285,21297,21308,21319,21330,21341,21353,21364,21375,21387,21398,
+21409,21420,21431,21443,21454,21465,21476,21488,21499,21510,21522,21533,
+21544,21555,21566,21577,21588,21600,21611,21622,21633,21645,21656,21667,
+21678,21689,21701,21712,21723,21734,21745,21756,21768,21779,21790,21801,
+21812,21823,21834,21846,21857,21868,21879,21890,21901,21913,21924,21935,
+21946,21957,21968,21979,21990,22001,22012,22024,22035,22046,22057,22068,
+22079,22090,22101,22112,22123,22135,22146,22157,22168,22179,22190,22201,
+22212,22223,22234,22245,22256,22267,22278,22289,22300,22311,22322,22334,
+22345,22356,22366,22377,22388,22400,22411,22422,22433,22443,22454,22466,
+22477,22488,22499,22509,22520,22532,22543,22553,22564,22575,22587,22597,
+22608,22619,22630,22641,22652,22663,22674,22685,22696,22707,22718,22729,
+22740,22750,22761,22773,22783,22794,22805,22816,22827,22838,22849,22860,
+22870,22881,22892,22903,22914,22925,22936,22947,22958,22968,22979,22990,
+23001,23012,23023,23033,23044,23055,23066,23077,23087,23098,23109,23120,
+23131,23142,23152,23163,23174,23185,23196,23206,23217,23228,23239,23249,
+23260,23271,23282,23293,23303,23314,23325,23336,23346,23357,23368,23379,
+23389,23400,23411,23422,23432,23443,23453,23465,23475,23486,23496,23507,
+23518,23529,23539,23550,23561,23571,23582,23593,23603,23614,23625,23635,
+23646,23657,23667,23678,23688,23699,23710,23720,23731,23742,23752,23763,
+23773,23784,23795,23805,23816,23826,23837,23848,23858,23869,23880,23890,
+23900,23911,23922,23932,23943,23953,23964,23974,23985,23995,24006,24017,
+24027,24037,24048,24059,24069,24079,24090,24101,24111,24121,24132,24142,
+24153,24163,24174,24184,24195,24205,24216,24226,24236,24247,24258,24268,
+24278,24289,24299,24309,24320,24331,24341,24351,24362,24372,24382,24393,
+24403,24414,24424,24434,24445,24455,24465,24476,24486,24496,24507,24517,
+24527,24538,24548,24558,24569,24579,24589,24600,24610,24620,24631,24641,
+24651,24661,24672,24682,24692,24702,24713,24723,24733,24743,24753,24764,
+24774,24784,24795,24805,24815,24825,24836,24846,24856,24866,24876,24886,
+24897,24907,24917,24927,24937,24947,24957,24968,24978,24988,24998,25008,
+25018,25029,25039,25049,25059,25069,25079,25089,25099,25109,25120,25130,
+25140,25150,25160,25170,25180,25190,25200,25210,25220,25230,25240,25250,
+25260,25270,25280,25290,25300,25310,25320,25330,25340,25350,25360,25370,
+25380,25390,25400,25410,25420,25430,25440,25450,25460,25470,25480,25490,
+25499,25510,25519,25529,25539,25549,25559,25569,25579,25589,25598,25608,
+25618,25628,25638,25648,25657,25667,25677,25687,25697,25707,25716,25726,
+25736,25746,25756,25765,25775,25785,25795,25805,25814,25824,25834,25844,
+25854,25863,25873,25883,25892,25902,25912,25921,25931,25941,25950,25960,
+25970,25980,25989,25999,26009,26018,26028,26038,26047,26057,26066,26076,
+26086,26095,26105,26115,26124,26134,26143,26153,26163,26172,26182,26191,
+26201,26210,26220,26230,26239,26249,26258,26268,26277,26287,26296,26306,
+26315,26325,26335,26344,26353,26363,26372,26382,26391,26401,26410,26419,
+26429,26438,26448,26457,26467,26476,26486,26495,26504,26514,26523,26533,
+26542,26552,26561,26570,26580,26589,26598,26607,26617,26626,26636,26645,
+26654,26664,26673,26682,26691,26701,26710,26719,26729,26738,26747,26756,
+26766,26775,26784,26793,26803,26812,26821,26830,26840,26849,26858,26867,
+26877,26885,26895,26904,26913,26922,26931,26941,26949,26959,26968,26977,
+26986,26995,27004,27014,27022,27032,27041,27050,27059,27068,27077,27086,
+27095,27104,27113,27123,27131,27141,27149,27159,27167,27177,27185,27195,
+27203,27213,27221,27231,27239,27249,27257,27266,27275,27284,27293,27302,
+27311,27320,27329,27338,27346,27356,27364,27373,27382,27391,27400,27409,
+27418,27426,27436,27444,27453,27462,27471,27479,27488,27497,27506,27515,
+27523,27532,27541,27550,27558,27567,27576,27585,27593,27602,27611,27620,
+27629,27637,27646,27654,27663,27672,27681,27689,27698,27707,27715,27724,
+27732,27741,27750,27759,27767,27776,27785,27793,27802,27810,27819,27827,
+27836,27845,27853,27862,27870,27879,27887,27896,27904,27913,27921,27930,
+27938,27947,27955,27964,27972,27981,27989,27998,28006,28014,28023,28032,
+28040,28048,28056,28065,28074,28082,28090,28098,28107,28116,28124,28132,
+28140,28149,28157,28165,28174,28182,28190,28199,28207,28215,28224,28232,
+28240,28249,28257,28265,28273,28282,28290,28298,28306,28315,28323,28331,
+28340,28348,28357,28365,28373,28381,28389,28398,28405,28414,28422,28430,
+28438,28446,28454,28463,28471,28479,28487,28495,28503,28511,28519,28527,
+28535,28543,28551,28559,28568,28575,28583,28592,28599,28607,28616,28623,
+28631,28640,28647,28655,28663,28671,28679,28687,28695,28703,28711,28718,
+28727,28735,28742,28750,28758,28766,28774,28782,28790,28797,28805,28813,
+28821,28829,28837,28844,28852,28860,28868,28875,28883,28891,28899,28906,
+28914,28922,28929,28937,28945,28953,28960,28968,28976,28983,28991,28999,
+29007,29014,29022,29030,29037,29045,29052,29060,29067,29075,29083,29090,
+29098,29105,29113,29121,29128,29136,29143,29151,29158,29166,29173,29181,
+29188,29196,29203,29211,29218,29226,29233,29241,29248,29255,29263,29270,
+29278,29285,29293,29300,29308,29315,29322,29330,29337,29344,29351,29359,
+29366,29374,29381,29388,29396,29403,29410,29417,29425,29432,29439,29446,
+29454,29461,29468,29476,29482,29490,29497,29504,29512,29518,29526,29533,
+29540,29547,29554,29561,29569,29576,29583,29590,29597,29604,29611,29619,
+29626,29633,29640,29647,29654,29661,29668,29675,29682,29689,29696,29703,
+29710,29717,29724,29731,29738,29745,29752,29759,29766,29773,29780,29787,
+29794,29801,29807,29814,29821,29828,29835,29842,29849,29855,29862,29869,
+29876,29883,29890,29896,29903,29910,29916,29923,29930,29937,29944,29951,
+29957,29964,29970,29977,29984,29991,29998,30004,30011,30018,30024,30031,
+30037,30044,30051,30057,30064,30071,30077,30084,30090,30097,30104,30110,
+30117,30123,30130,30137,30143,30150,30156,30162,30169,30175,30182,30188,
+30195,30201,30208,30214,30221,30227,30234,30240,30246,30253,30259,30266,
+30272,30278,30285,30291,30298,30304,30310,30317,30323,30329,30336,30342,
+30348,30355,30361,30367,30373,30379,30386,30392,30398,30404,30411,30417,
+30423,30429,30436,30442,30448,30454,30460,30466,30473,30479,30485,30491,
+30497,30503,30509,30515,30522,30528,30534,30540,30546,30552,30558,30564,
+30570,30576,30582,30588,30594,30600,30606,30612,30618,30624,30630,30636,
+30642,30648,30654,30659,30665,30671,30677,30683,30689,30695,30701,30706,
+30712,30718,30724,30730,30735,30741,30747,30753,30759,30764,30770,30776,
+30782,30788,30793,30799,30805,30811,30816,30822,30828,30833,30839,30844,
+30850,30856,30861,30867,30873,30878,30884,30890,30895,30901,30906,30912,
+30917,30923,30928,30934,30939,30945,30950,30956,30962,30967,30973,30978,
+30984,30989,30994,31000,31005,31011,31016,31022,31027,31033,31038,31043,
+31049,31054,31059,31065,31070,31076,31081,31086,31091,31097,31102,31107,
+31113,31118,31123,31128,31134,31139,31144,31149,31155,31160,31165,31170,
+31175,31180,31185,31191,31196,31201,31206,31211,31216,31221,31227,31232,
+31237,31242,31247,31252,31257,31262,31267,31272,31277,31282,31287,31293,
+31297,31302,31307,31312,31317,31322,31327,31332,31337,31342,31347,31352,
+31357,31361,31366,31372,31376,31381,31386,31391,31396,31400,31405,31410,
+31415,31420,31424,31429,31434,31438,31444,31448,31453,31458,31462,31467,
+31472,31476,31481,31486,31491,31495,31500,31504,31509,31514,31518,31523,
+31528,31532,31537,31541,31546,31551,31555,31559,31564,31569,31573,31578,
+31582,31587,31591,31596,31600,31605,31609,31613,31618,31622,31627,31631,
+31636,31640,31644,31649,31653,31658,31662,31666,31671,31675,31679,31684,
+31688,31692,31696,31701,31705,31709,31714,31718,31722,31726,31731,31735,
+31739,31743,31747,31751,31756,31760,31764,31768,31772,31776,31781,31785,
+31789,31793,31797,31801,31805,31809,31813,31817,31822,31825,31829,31834,
+31837,31841,31846,31849,31853,31858,31861,31865,31869,31873,31877,31881,
+31885,31889,31893,31896,31901,31904,31908,31912,31916,31920,31924,31927,
+31931,31935,31939,31943,31946,31950,31954,31958,31961,31965,31969,31973,
+31976,31980,31984,31987,31991,31995,31998,32002,32006,32009,32013,32016,
+32020,32024,32027,32031,32034,32038,32041,32045,32049,32052,32056,32059,
+32063,32066,32070,32073,32076,32080,32083,32087,32090,32094,32097,32101,
+32104,32107,32111,32114,32118,32121,32124,32128,32131,32134,32138,32141,
+32144,32148,32151,32154,32157,32160,32164,32167,32171,32173,32177,32180,
+32183,32186,32190,32193,32196,32199,32202,32205,32208,32212,32215,32218,
+32221,32224,32227,32230,32233,32236,32239,32242,32245,32249,32251,32255,
+32257,32261,32263,32266,32269,32272,32275,32278,32281,32284,32287,32290,
+32292,32296,32298,32301,32304,32307,32310,32313,32316,32318,32321,32324,
+32327,32329,32332,32335,32338,32340,32343,32346,32349,32351,32354,32357,
+32359,32362,32365,32367,32370,32373,32375,32378,32381,32383,32386,32388,
+32391,32394,32396,32399,32401,32404,32406,32409,32411,32414,32416,32419,
+32421,32424,32426,32429,32431,32433,32436,32438,32441,32443,32445,32448,
+32450,32453,32455,32457,32460,32462,32464,32467,32469,32471,32473,32476,
+32478,32480,32482,32485,32487,32489,32491,32494,32496,32498,32500,32502,
+32504,32507,32509,32511,32513,32515,32517,32519,32521,32523,32526,32527,
+32530,32532,32534,32536,32538,32540,32542,32544,32546,32548,32550,32551,
+32554,32556,32557,32559,32561,32563,32565,32567,32569,32571,32573,32575,
+32576,32578,32580,32582,32584,32586,32587,32589,32591,32593,32594,32596,
+32598,32599,32601,32603,32605,32606,32608,32610,32611,32613,32615,32617,
+32618,32620,32621,32623,32624,32626,32628,32629,32631,32632,32634,32635,
+32637,32638,32640,32641,32643,32644,32646,32647,32649,32650,32652,32653,
+32654,32656,32657,32659,32660,32661,32663,32664,32665,32667,32668,32670,
+32671,32672,32673,32675,32676,32677,32678,32680,32681,32682,32683,32685,
+32686,32687,32689,32689,32691,32692,32693,32694,32695,32696,32698,32699,
+32700,32701,32702,32703,32704,32705,32706,32707,32708,32709,32710,32711,
+32712,32713,32714,32715,32716,32717,32718,32719,32720,32721,32722,32723,
+32724,32725,32725,32726,32727,32728,32729,32730,32731,32731,32732,32733,
+32734,32734,32735,32736,32737,32737,32738,32739,32739,32740,32741,32742,
+32742,32743,32743,32744,32745,32745,32746,32747,32747,32748,32749,32749,
+32749,32750,32751,32751,32752,32752,32753,32754,32754,32755,32755,32755,
+32756,32756,32757,32757,32758,32758,32758,32759,32759,32760,32760,32761,
+32761,32761,32761,32762,32762,32762,32763,32763,32763,32763,32764,32764,
+32764,32765,32765,32765,32765,32766,32766,32766,32766,32766,32767,32767,
+32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32766,32766,
+32766,32766,32766,32765,32765,32765,32765,32764,32764,32764,32764,32763,
+32763,32763,32762,32762,32762,32761,32761,32761,32761,32760,32760,32759,
+32759,32759,32758,32758,32757,32757,32756,32756,32755,32755,32755,32754,
+32754,32753,32753,32752,32751,32751,32750,32750,32749,32749,32748,32748,
+32747,32746,32746,32745,32744,32743,32743,32743,32742,32741,32740,32740,
+32739,32738,32737,32737,32736,32735,32734,32734,32733,32732,32731,32731,
+32730,32729,32728,32727,32726,32725,32725,32724,32723,32722,32721,32720,
+32719,32718,32717,32716,32715,32714,32713,32713,32712,32710,32709,32708,
+32707,32707,32705,32704,32703,32702,32701,32700,32699,32698,32696,32695,
+32694,32693,32692,32691,32689,32689,32687,32686,32685,32683,32683,32681,
+32680,32679,32677,32676,32675,32674,32672,32671,32670,32668,32667,32666,
+32665,32663,32662,32660,32659,32658,32656,32655,32653,32652,32650,32649,
+32647,32646,32645,32643,32641,32640,32639,32637,32635,32634,32632,32631,
+32629,32628,32626,32624,32623,32622,32620,32618,32617,32615,32613,32611,
+32610,32608,32606,32605,32603,32601,32600,32598,32596,32594,32593,32591,
+32589,32587,32586,32584,32582,32580,32578,32576,32575,32573,32571,32569,
+32567,32565,32563,32562,32560,32558,32556,32554,32552,32550,32548,32546,
+32544,32542,32540,32538,32536,32534,32532,32530,32528,32526,32524,32521,
+32520,32517,32515,32513,32511,32509,32507,32505,32503,32500,32498,32496,
+32494,32491,32490,32487,32485,32483,32480,32478,32476,32473,32472,32469,
+32467,32465,32462,32460,32458,32455,32453,32450,32448,32446,32443,32441,
+32438,32436,32434,32431,32429,32426,32424,32421,32419,32417,32414,32412,
+32409,32406,32404,32401,32399,32396,32394,32391,32388,32386,32383,32381,
+32378,32376,32373,32370,32368,32365,32362,32360,32357,32354,32352,32349,
+32346,32344,32341,32338,32335,32333,32330,32327,32324,32322,32319,32316,
+32313,32310,32307,32304,32302,32299,32296,32293,32290,32287,32284,32281,
+32279,32275,32273,32270,32267,32264,32261,32258,32255,32252,32249,32246,
+32243,32240,32237,32233,32231,32227,32225,32221,32218,32215,32212,32209,
+32206,32202,32200,32196,32193,32190,32187,32184,32180,32177,32174,32171,
+32167,32164,32161,32158,32154,32151,32148,32145,32142,32138,32135,32131,
+32128,32125,32121,32118,32115,32112,32108,32105,32101,32098,32094,32091,
+32088,32084,32081,32077,32074,32070,32067,32063,32060,32056,32052,32049,
+32045,32042,32039,32035,32031,32027,32024,32021,32017,32013,32009,32006,
+32003,31999,31995,31991,31988,31984,31980,31977,31973,31969,31966,31962,
+31958,31955,31950,31947,31943,31939,31936,31931,31928,31924,31920,31916,
+31913,31909,31905,31901,31897,31893,31889,31885,31882,31877,31874,31870,
+31866,31862,31858,31854,31850,31846,31842,31838,31834,31830,31826,31822,
+31818,31814,31810,31805,31802,31798,31793,31789,31785,31781,31777,31773,
+31769,31764,31760,31756,31752,31748,31744,31739,31735,31731,31727,31722,
+31718,31714,31710,31706,31701,31697,31693,31688,31684,31680,31675,31671,
+31667,31662,31658,31654,31649,31645,31641,31636,31632,31627,31623,31618,
+31614,31610,31605,31600,31596,31592,31587,31583,31578,31574,31569,31564,
+31560,31556,31551,31546,31542,31537,31533,31528,31523,31519,31514,31510,
+31505,31500,31496,31491,31486,31482,31477,31472,31468,31463,31458,31454,
+31449,31444,31439,31434,31430,31425,31420,31415,31411,31406,31401,31396,
+31391,31386,31382,31377,31372,31367,31362,31357,31353,31347,31342,31338,
+31333,31328,31323,31318,31313,31308,31303,31298,31293,31288,31283,31278,
+31273,31268,31263,31258,31253,31248,31243,31238,31233,31227,31222,31217,
+31212,31207,31202,31197,31191,31186,31181,31176,31171,31166,31161,31155,
+31150,31145,31139,31134,31129,31124,31119,31113,31108,31103,31097,31092,
+31087,31082,31076,31071,31065,31060,31055,31049,31044,31039,31033,31028,
+31023,31017,31011,31006,31001,30995,30990,30984,30979,30974,30968,30962,
+30957,30951,30946,30940,30935,30929,30924,30918,30913,30907,30902,30896,
+30890,30884,30879,30873,30868,30862,30856,30851,30845,30840,30834,30828,
+30823,30817,30811,30806,30800,30794,30788,30782,30777,30771,30765,30759,
+30754,30748,30742,30736,30730,30725,30719,30713,30707,30701,30695,30690,
+30684,30678,30672,30666,30660,30654,30648,30643,30637,30631,30625,30619,
+30613,30607,30601,30595,30589,30583,30577,30571,30565,30559,30553,30547,
+30541,30535,30528,30522,30516,30510,30504,30498,30492,30486,30480,30473,
+30467,30461,30455,30449,30443,30436,30430,30424,30418,30411,30405,30399,
+30393,30386,30380,30374,30368,30361,30355,30349,30343,30337,30330,30324,
+30318,30311,30305,30298,30292,30286,30279,30273,30266,30260,30254,30247,
+30241,30234,30228,30222,30215,30209,30202,30196,30189,30183,30176,30170,
+30163,30157,30150,30144,30137,30131,30124,30118,30111,30104,30098,30091,
+30084,30078,30072,30065,30058,30052,30045,30038,30032,30025,30018,30012,
+30005,29998,29992,29985,29978,29971,29965,29958,29951,29945,29938,29931,
+29924,29917,29911,29904,29897,29890,29884,29877,29870,29863,29856,29849,
+29843,29836,29829,29822,29815,29808,29801,29794,29788,29781,29774,29767,
+29759,29753,29746,29739,29732,29725,29718,29711,29704,29697,29690,29683,
+29676,29669,29662,29655,29648,29641,29633,29627,29620,29612,29605,29598,
+29591,29584,29577,29570,29562,29555,29548,29541,29534,29527,29519,29512,
+29505,29498,29491,29483,29476,29469,29462,29455,29447,29440,29433,29426,
+29418,29411,29404,29396,29389,29382,29374,29367,29360,29352,29345,29338,
+29331,29323,29316,29308,29301,29294,29286,29279,29271,29264,29256,29249,
+29241,29234,29227,29219,29211,29204,29197,29189,29182,29174,29167,29159,
+29151,29144,29137,29129,29121,29114,29106,29099,29091,29084,29076,29068,
+29061,29053,29046,29038,29031,29023,29015,29007,29000,28992,28984,28977,
+28969,28961,28954,28946,28938,28930,28923,28915,28907,28899,28892,28884,
+28876,28868,28861,28853,28845,28838,28830,28822,28814,28806,28798,28790,
+28783,28775,28767,28759,28751,28743,28736,28728,28720,28712,28704,28696,
+28688,28680,28672,28664,28656,28648,28640,28632,28624,28616,28609,28600,
+28592,28585,28576,28568,28561,28552,28544,28536,28528,28520,28512,28504,
+28496,28488,28480,28471,28464,28455,28447,28439,28431,28423,28415,28407,
+28399,28390,28382,28374,28366,28357,28350,28341,28332,28324,28315,28307,
+28299,28291,28283,28274,28266,28258,28249,28241,28233,28225,28217,28208,
+28200,28192,28183,28175,28167,28158,28150,28141,28133,28125,28116,28108,
+28100,28092,28083,28074,28066,28058,28050,28041,28032,28024,28015,28007,
+27999,27990,27982,27973,27965,27956,27948,27939,27931,27922,27914,27906,
+27897,27888,27880,27871,27863,27854,27846,27837,27828,27820,27811,27803,
+27794,27785,27777,27768,27760,27751,27742,27734,27725,27716,27708,27699,
+27690,27682,27673,27665,27656,27647,27638,27629,27621,27612,27604,27595,
+27586,27577,27569,27560,27551,27542,27533,27525,27516,27507,27498,27490,
+27481,27472,27463,27454,27445,27436,27428,27419,27410,27401,27392,27383,
+27375,27365,27357,27348,27339,27330,27321,27312,27303,27294,27286,27276,
+27268,27258,27250,27241,27232,27223,27214,27205,27196,27187,27178,27169,
+27160,27151,27142,27133,27123,27114,27105,27096,27087,27078,27069,27060,
+27051,27042,27033,27024,27015,27005,26997,26987,26978,26969,26960,26951,
+26942,26932,26923,26914,26905,26896,26887,26877,26868,26859,26850,26841,
+26831,26822,26813,26804,26794,26785,26776,26767,26757,26748,26739,26730,
+26720,26711,26702,26693,26683,26674,26665,26655,26646,26637,26627,26618,
+26609,26600,26590,26581,26571,26562,26552,26543,26534,26524,26515,26506,
+26496,26487,26477,26468,26459,26449,26440,26430,26421,26411,26402,26392,
+26383,26373,26364,26354,26345,26335,26326,26317,26307,26298,26288,26279,
+26269,26259,26250,26240,26231,26221,26212,26202,26192,26183,26173,26164,
+26154,26145,26135,26125,26116,26106,26097,26087,26077,26068,26058,26048,
+26039,26029,26020,26010,26000,25991,25981,25971,25962,25952,25942,25932,
+25923,25913,25903,25894,25884,25874,25864,25854,25845,25835,25825,25816,
+25806,25796,25786,25776,25767,25757,25747,25737,25727,25718,25708,25698,
+25688,25679,25668,25659,25649,25639,25629,25619,25609,25600,25590,25580,
+25570,25560,25550,25541,25530,25521,25511,25501,25491,25481,25471,25461,
+25451,25441,25431,25421,25411,25402,25391,25381,25372,25361,25352,25342,
+25331,25322,25312,25301,25292,25282,25271,25262,25252,25241,25231,25222,
+25211,25201,25191,25181,25171,25161,25151,25141,25131,25121,25111,25101,
+25090,25080,25070,25060,25050,25040,25030,25020,25010,24999,24989,24979,
+24969,24959,24949,24939,24928,24918,24908,24898,24888,24878,24867,24857,
+24847,24837,24826,24816,24806,24796,24786,24776,24765,24755,24745,24735,
+24724,24714,24704,24693,24683,24673,24662,24652,24642,24632,24621,24611,
+24601,24590,24580,24570,24560,24549,24539,24529,24518,24508,24498,24487,
+24477,24467,24456,24446,24435,24425,24415,24404,24394,24384,24373,24363,
+24352,24342,24332,24321,24311,24301,24290,24280,24269,24259,24248,24238,
+24228,24217,24206,24196,24186,24175,24165,24154,24144,24133,24123,24112,
+24102,24091,24081,24070,24060,24049,24039,24028,24018,24007,23997,23986,
+23976,23965,23954,23944,23934,23923,23912,23902,23891,23880,23870,23860,
+23849,23838,23828,23817,23807,23796,23785,23775,23764,23754,23743,23732,
+23722,23711,23700,23690,23679,23669,23658,23647,23637,23626,23615,23604,
+23594,23583,23573,23562,23551,23541,23530,23519,23508,23498,23487,23477,
+23466,23455,23444,23434,23423,23412,23401,23391,23380,23369,23358,23348,
+23337,23326,23315,23305,23294,23283,23273,23262,23251,23240,23230,23218,
+23208,23197,23186,23176,23164,23154,23143,23132,23122,23110,23100,23089,
+23078,23067,23056,23045,23035,23024,23013,23002,22991,22981,22970,22959,
+22948,22937,22926,22915,22905,22893,22883,22872,22861,22850,22839,22828,
+22817,22806,22796,22785,22774,22763,22752,22741,22730,22719,22708,22697,
+22686,22675,22665,22653,22642,22632,22621,22610,22599,22588,22577,22566,
+22555,22544,22533,22522,22511,22500,22489,22478,22467,22456,22445,22434,
+22423,22412,22401,22390,22379,22368,22357,22346,22335,22324,22313,22302,
+22291,22280,22268,22257,22246,22236,22225,22213,22202,22191,22180,22169,
+22158,22147,22136,22125,22114,22103,22092,22081,22069,22058,22047,22036,
+22025,22014,22003,21991,21980,21969,21958,21947,21936,21925,21914,21903,
+21891,21880,21869,21858,21847,21836,21825,21813,21802,21791,21780,21769,
+21758,21746,21735,21724,21713,21702,21690,21679,21668,21657,21646,21635,
+21624,21612,21601,21590,21579,21568,21556,21545,21534,21523,21511,21500,
+21489,21478,21467,21455,21444,21433,21422,21410,21399,21388,21377,21365,
+21354,21343,21332,21321,21309,21298,21287,21275,21264,21253,21242,21230,
+21219,21208,21197,21185,21174,21163,21151,21140,21129,21118,21106,21095,
+21084,21072,21061,21050,21039,21027,21016,21004,20993,20982,20971,20959,
+20948,20937,20926,20914,20903,20891,20880,20869,20857,20846,20835,20824,
+20812,20801,20789,20778,20767,20755,20744,20733,20721,20710,20698,20687,
+20676,20664,20653,20642,20630,20619,20607,20596,20585,20573,20562,20551,
+20539,20528,20517,20505,20493,20482,20471,20459,20448,20437,20425,20414,
+20402,20391,20379,20368,20357,20345,20334,20323,20311,20300,20288,20277,
+20265,20254,20243,20231,20220,20208,20197,20186,20174,20162,20151,20140,
+20128,20117,20105,20094,20083,20071,20059,20048,20036,20025,20014,20002,
+19991,19979,19968,19957,19945,19933,19922,19910,19899,19888,19876,19865,
+19853,19842,19830,19819,19807,19796,19784,19773,19761,19750,19738,19727,
+19715,19704,19692,19681,19669,19658,19646,19635,19623,19612,19600,19589,
+19578,19566,19554,19543,19531,19520,19508,19497,19485,19474,19462,19451,
+19439,19428,19416,19404,19393,19381,19370,19359,19347,19336,19324,19313,
+19301,19289,19278,19266,19255,19243,19232,19220,19209,19197,19186,19174,
+19163,19151,19139,19128,19116,19105,19093,19082,19070,19059,19047,19036,
+19024,19012,19000,18989,18977,18966,18954,18943,18931,18920,18908,18897,
+18885,18874,18862,18850,18839,18827,18816,18804,18793,18781,18770,18758,
+18746,18735,18723,18712,18700,18688,18677,18665,18654,18642,18631,18619,
+18608,18596,18584,18573,18561,18549,18538,18526,18515,18503,18492,18480,
+18468,18457,18445,18434,18422,18411,18399,18387,18376,18364,18352,18341,
+18329,18318,18306,18295,18283,18272,18260,18248,18236,18225,18213,18202,
+18190,18179,18167,18156,18144,18132,18121,18109,18098,18086,18074,18063,
+18051,18039,18028,18016,18005,17993,17982,17970,17958,17947,17935,17923,
+17912,17900,17889,17877,17865,17854,17842,17831,17819,17808,17796,17785,
+17773,17761,17749,17738,17726,17715,17703,17691,17680,17668,17657,17645,
+17632,17621,17609,17597,17586,17574,17562,17551,17539,17527,17516,17504,
+17493,17481,17470,17458,17447,17435,17423,17412,17400,17388,17377,17365,
+17354,17342,17330,17319,17307,17296,17284,17273,17261,17249,17237,17226,
+17214,17203,17191,17180,17168,17156,17145,17133,17122,17110,17099,17087,
+17075,17063,17052,17040,17029,17017,17006,16994,16983,16971,16959,16948,
+16936,16924,16913,16901,16890,16878,16867,16855,16843,16832,16820,16809,
+16797,16786,16774,16762,16751,16739,16727,16716,16704,16693,16681,16670,
+16658,16647,16635,16624,16612,16600,16589,16577,16565,16554,16542,16531,
+16519,16508,16496,16485,16473,16461,16450,16438,16427,16415,16404,16392,
+16380,16369,16357,16346,16334,16323,16311,16299,16288,16276,16265,16253,
+16242,16230,16219,16207,16196,16184,16172,16161,16149,16138,16126,16115,
+16103,16092,16080,16069,16057,16046,16034,16022,16011,15999,15988,15976,
+15965,15953,15942,15930,15919,15907,15896,15884,15872,15861,15849,15838,
+15826,15815,15804,15792,15781,15769,15757,15746,15734,15723,15711,15700,
+15688,15677,15665,15654,15643,15631,15619,15608,15596,15585,15573,15562,
+15550,15539,15528,15516,15504,15493,15481,15470,15458,15447,15436,15424,
+15413,15401,15390,15378,15366,15355,15344,15332,15321,15309,15298,15287,
+15275,15264,15252,15240,15229,15218,15206,15195,15183,15172,15161,15149,
+15137,15126,15114,15103,15092,15080,15069,15058,15046,15035,15023,15012,
+15000,14989,14977,14966,14955,14943,14932,14921,14909,14897,14886,14875,
+14863,14852,14841,14829,14818,14806,14795,14783,14772,14761,14749,14738,
+14727,14715,14704,14692,14681,14670,14658,14647,14636,14624,14613,14602,
+14590,14579,14567,14556,14545,14533,14522,14511,14499,14488,14476,14465,
+14454,14443,14431,14420,14409,14397,14386,14374,14363,14352,14341,14329,
+14318,14307,14295,14284,14273,14261,14250,14239,14228,14216,14205,14193,
+14182,14171,14160,14148,14137,14126,14114,14103,14092,14081,14069,14058,
+14047,14036,14024,14013,14002,13990,13979,13968,13957,13946,13934,13923,
+13912,13900,13889,13878,13867,13856,13844,13833,13822,13811,13799,13788,
+13777,13766,13754,13743,13732,13721,13710,13699,13687,13676,13665,13654,
+13643,13631,13620,13609,13598,13586,13575,13564,13553,13542,13531,13519,
+13508,13497,13486,13475,13464,13453,13441,13430,13419,13408,13397,13386,
+13374,13363,13352,13341,13330,13319,13308,13297,13286,13275,13264,13252,
+13241,13230,13219,13208,13197,13186,13175,13164,13152,13141,13130,13119,
+13108,13097,13086,13075,13064,13053,13042,13031,13020,13009,12998,12987,
+12976,12965,12953,12942,12931,12920,12910,12899,12887,12876,12865,12854,
+12843,12833,12821,12810,12799,12788,12778,12767,12755,12744,12733,12723,
+12712,12700,12689,12679,12668,12657,12646,12635,12624,12613,12602,12591,
+12580,12569,12558,12547,12537,12526,12514,12504,12493,12482,12471,12460,
+12449,12438,12427,12417,12406,12395,12384,12373,12362,12351,12340,12329,
+12319,12308,12297,12286,12275,12264,12254,12243,12232,12221,12210,12199,
+12189,12177,12167,12156,12145,12135,12123,12113,12102,12091,12081,12069,
+12059,12048,12037,12027,12016,12005,11994,11984,11972,11962,11951,11941,
+11930,11919,11908,11897,11887,11876,11865,11855,11844,11833,11822,11812,
+11801,11790,11780,11769,11758,11748,11737,11726,11715,11705,11694,11684,
+11673,11662,11652,11641,11630,11619,11609,11598,11587,11577,11566,11556,
+11545,11534,11524,11513,11503,11492,11481,11471,11461,11450,11439,11429,
+11418,11407,11397,11386,11376,11365,11355,11344,11334,11323,11312,11302,
+11291,11281,11270,11260,11249,11239,11228,11218,11207,11197,11186,11176,
+11165,11155,11144,11134,11124,11113,11102,11092,11082,11071,11061,11050,
+11040,11029,11019,11009,10998,10987,10977,10967,10956,10946,10936,10925,
+10915,10904,10894,10883,10873,10863,10853,10842,10832,10821,10811,10801,
+10790,10780,10769,10759,10749,10739,10728,10718,10708,10697,10687,10677,
+10667,10656,10646,10636,10625,10615,10605,10594,10584,10574,10564,10553,
+10543,10533,10522,10512,10502,10492,10482,10472,10462,10451,10441,10431,
+10420,10410,10400,10390,10380,10370,10360,10349,10339,10329,10319,10309,
+10299,10288,10278,10268,10258,10248,10238,10227,10217,10207,10197,10187,
+10177,10167,10157,10147,10137,10127,10117,10107,10096,10086,10077,10066,
+10056,10046,10036,10026,10016,10006,9996,9986,9976,9966,9956,9946,
+9936,9926,9916,9906,9896,9886,9876,9866,9856,9847,9836,9827,
+9817,9807,9797,9787,9777,9767,9757,9747,9737,9728,9717,9708,
+9698,9688,9678,9668,9658,9649,9639,9629,9619,9609,9599,9590,
+9580,9570,9560,9550,9541,9531,9521,9511,9501,9492,9482,9472,
+9462,9452,9443,9433,9423,9414,9404,9394,9384,9374,9365,9355,
+9345,9336,9326,9316,9307,9297,9287,9277,9268,9259,9249,9239,
+9229,9220,9210,9200,9191,9181,9172,9162,9152,9143,9133,9124,
+9114,9104,9095,9085,9076,9066,9057,9047,9037,9028,9018,9009,
+9000,8990,8980,8971,8961,8952,8942,8933,8923,8914,8904,8895,
+8886,8876,8867,8857,8848,8838,8829,8819,8810,8801,8791,8782,
+8772,8763,8753,8744,8735,8725,8716,8707,8697,8688,8679,8669,
+8660,8651,8641,8632,8622,8613,8604,8595,8585,8576,8567,8558,
+8548,8539,8530,8520,8511,8502,8493,8483,8474,8465,8456,8446,
+8437,8428,8419,8410,8401,8392,8382,8373,8364,8355,8345,8337,
+8327,8318,8309,8300,8291,8282,8272,8263,8254,8245,8236,8227,
+8218,8209,8200,8191,8182,8173,8164,8155,8146,8136,8127,8118,
+8109,8100,8091,8082,8073,8064,8055,8047,8037,8029,8019,8011,
+8002,7993,7984,7975,7966,7957,7948,7939,7930,7922,7912,7904,
+7895,7886,7877,7868,7859,7851,7842,7833,7824,7815,7806,7797,
+7789,7780,7771,7762,7754,7745,7736,7727,7718,7710,7701,7692,
+7683,7675,7666,7658,7649,7640,7631,7622,7614,7605,7597,7588,
+7579,7570,7562,7553,7544,7536,7527,7519,7510,7502,7493,7484,
+7476,7467,7459,7450,7442,7433,7424,7416,7407,7399,7390,7381,
+7373,7364,7356,7347,7339,7330,7322,7314,7305,7297,7288,7279,
+7271,7263,7254,7246,7237,7229,7220,7212,7204,7195,7187,7178,
+7170,7162,7153,7145,7137,7129,7120,7112,7104,7095,7087,7079,
+7070,7062,7054,7045,7037,7029,7020,7012,7004,6996,6988,6979,
+6971,6963,6954,6946,6937,6929,6921,6912,6905,6896,6888,6880,
+6872,6864,6856,6847,6839,6831,6823,6815,6807,6799,6791,6783,
+6774,6767,6758,6750,6742,6734,6726,6718,6710,6702,6694,6686,
+6678,6670,6662,6654,6646,6638,6630,6622,6614,6606,6599,6591,
+6582,6575,6567,6559,6551,6543,6535,6527,6520,6512,6504,6496,
+6488,6480,6473,6465,6457,6449,6441,6433,6425,6418,6410,6402,
+6395,6387,6379,6371,6364,6356,6348,6340,6333,6325,6317,6310,
+6302,6294,6286,6279,6271,6263,6256,6248,6241,6233,6226,6218,
+6210,6202,6195,6187,6180,6172,6165,6157,6149,6142,6135,6127,
+6119,6112,6105,6097,6089,6082,6075,6067,6059,6052,6045,6037,
+6030,6022,6015,6008,6000,5992,5985,5978,5970,5963,5955,5948,
+5941,5934,5926,5919,5912,5904,5897,5889,5883,5875,5868,5860,
+5853,5846,5839,5831,5824,5817,5810,5803,5795,5788,5781,5774,
+5767,5759,5752,5745,5738,5731,5723,5716,5709,5702,5695,5688,
+5681,5673,5666,5660,5652,5645,5638,5631,5624,5617,5610,5603,
+5596,5589,5582,5575,5568,5561,5554,5547,5540,5533,5526,5519,
+5512,5505,5498,5492,5485,5478,5471,5464,5457,5450,5443,5437,
+5430,5423,5416,5409,5402,5396,5389,5382,5375,5368,5361,5355,
+5348,5341,5335,5328,5321,5314,5307,5301,5294,5287,5281,5274,
+5267,5261,5254,5247,5241,5234,5227,5221,5214,5208,5201,5194,
+5188,5181,5174,5168,5161,5155,5149,5142,5135,5129,5122,5116,
+5109,5103,5096,5090,5083,5077,5071,5064,5058,5051,5045,5038,
+5032,5025,5019,5012,5006,5000,4993,4987,4981,4974,4968,4962,
+4956,4949,4943,4937,4930,4924,4918,4911,4905,4899,4892,4886,
+4880,4874,4867,4861,4855,4849,4843,4836,4830,4824,4818,4812,
+4806,4800,4794,4788,4782,4775,4769,4763,4757,4751,4745,4739,
+4733,4727,4721,4715,4709,4703,4697,4691,4685,4679,4673,4667,
+4661,4655,4649,4643,4637,4631,4625,4619,4613,4607,4601,4595,
+4589,4584,4578,4572,4566,4560,4555,4549,4543,4537,4531,4526,
+4520,4514,4508,4503,4497,4491,4485,4480,4474,4468,4463,4457,
+4451,4445,4440,4434,4428,4423,4417,4412,4406,4400,4395,4389,
+4384,4378,4373,4367,4361,4356,4350,4345,4339,4334,4328,4323,
+4317,4312,4306,4301,4295,4290,4284,4279,4273,4268,4263,4257,
+4252,4246,4241,4235,4230,4225,4219,4214,4209,4204,4198,4193,
+4187,4182,4177,4172,4166,4161,4156,4150,4145,4140,4135,4130,
+4124,4119,4114,4109,4103,4098,4093,4088,4083,4078,4072,4067,
+4062,4057,4052,4047,4042,4037,4032,4027,4022,4017,4012,4006,
+4002,3997,3992,3987,3982,3976,3972,3967,3962,3957,3952,3947,
+3942,3937,3932,3927,3922,3917,3913,3908,3903,3898,3893,3888,
+3884,3879,3874,3869,3864,3860,3855,3850,3845,3840,3836,3831,
+3826,3821,3817,3812,3807,3803,3798,3793,3789,3784,3779,3775,
+3770,3765,3761,3756,3752,3747,3742,3738,3733,3729,3724,3720,
+3715,3711,3706,3702,3697,3693,3688,3684,3679,3675,3670,3666,
+3661,3657,3652,3648,3644,3639,3635,3631,3626,3622,3617,3613,
+3609,3604,3600,3596,3591,3587,3583,3579,3574,3570,3566,3561,
+3557,3553,3549,3545,3541,3536,3532,3528,3524,3519,3515,3511,
+3507,3503,3499,3495,3491,3487,3482,3478,3474,3470,3466,3462,
+3458,3454,3450,3446,3442,3438,3434,3430,3426,3422,3418,3414,
+3410,3406,3403,3398,3395,3391,3387,3383,3379,3375,3371,3368,
+3364,3360,3356,3352,3348,3344,3341,3337,3333,3330,3326,3322,
+3318,3314,3311,3307,3303,3300,3296,3292,3289,3285,3281,3278,
+3274,3271,3267,3263,3260,3256,3253,3249,3245,3242,3238,3235,
+3231,3228,3224,3221,3217,3213,3210,3206,3203,3199,3196,3193,
+3189,3186,3182,3179,3175,3172,3169,3165,3162,3159,3156,3152,
+3149,3145,3142,3139,3135,3132,3129,3126,3122,3119,3116,3113,
+3109,3106,3103,3100,3097,3093,3090,3087,3084,3081,3078,3074,
+3072,3068,3065,3062,3059,3056,3053,3050,3047,3043,3041,3037,
+3035,3031,3029,3025,3023,3019,3017,3013,3011,3008,3005,3002,
+2999,2996,2993,2990,2988,2984,2982,2979,2976,2973,2970,2967,
+2965,2962,2959,2956,2953,2951,2948,2945,2942,2940,2937,2934,
+2931,2929,2926,2923,2921,2918,2916,2913,2910,2907,2905,2902,
+2899,2897,2894,2892,2889,2887,2884,2881,2879,2876,2874,2871,
+2869,2867,2864,2862,2859,2856,2854,2852,2849,2847,2844,2842,
+2839,2837,2835,2832,2830,2828,2826,2823,2821,2819,2816,2814,
+2812,2809,2807,2805,2802,2800,2798,2796,2793,2791,2789,2787,
+2784,2783,2780,2778,2776,2774,2772,2770,2767,2766,2763,2761,
+2759,2757,2755,2753,2751,2749,2747,2745,2742,2741,2739,2736,
+2735,2733,2731,2729,2727,2725,2723,2721,2719,2717,2715,2713,
+2712,2710,2708,2706,2704,2702,2700,2699,2697,2695,2694,2692,
+2690,2688,2686,2685,2683,2681,2679,2678,2676,2674,2673,2671,
+2669,2668,2666,2664,2663,2661,2659,2658,2656,2655,2653,2652,
+2650,2648,2647,2646,2644,2642,2641,2640,2638,2636,2635,2634,
+2632,2631,2629,2628,2626,2625,2623,2622,2621,2619,2618,2616,
+2615,2614,2613,2611,2610,2609,2607,2606,2605,2604,2602,2601,
+2600,2598,2598,2596,2595,2594,2592,2592,2590,2589,2588,2587,
+2586,2585,2583,2582,2581,2580,2579,2578,2577,2576,2575,2574,
+2573,2572,2571,2570,2568,2568,2567,2566,2565,2564,2563,2562,
+2561,2560,2559,2558,2557,2556,2556,2555,2554,2553,2552,2551,
+2551,2550,2549,2548,2548,2547,2546,2545,2544,2544,2543,2542,
+2542,2541,2540,2539,2539,2538,2538,2537,2536,2536,2535,2534,
+2534,2533,2532,2532,2532,2531,2531,2530,2529,2529,2528,2528,
+2527,2527,2526,2526,2526,2525,2525,2524,2524,2523,2523,2522,
+2522,2522,2521,2521,2520,2520,2520,2520,2519,2519,2519,2518,
+2518,2518,2518,2517,2517,2517,2517,2516,2516,2516,2516,2515,
+2515,2515,2515,2515,2515,2514,2514,2514,2514,2514,2514,2514,
+2514,2514,2514,2514,2514,2514,2514,2514};
+const int32_t hamming_4096 [] = {2514,2514,2514,2514,2514,2514,2514,2514,2515,2515,2515,2516,
+2516,2517,2517,2518,2518,2519,2520,2520,2521,2522,2522,2523,
+2524,2525,2526,2527,2528,2529,2530,2531,2532,2533,2534,2536,
+2537,2538,2539,2541,2542,2544,2545,2547,2548,2550,2551,2553,
+2555,2556,2558,2560,2562,2564,2566,2568,2569,2572,2574,2576,
+2578,2580,2582,2584,2586,2589,2591,2593,2596,2598,2601,2604,
+2606,2609,2611,2614,2616,2619,2622,2625,2628,2630,2633,2636,
+2639,2642,2645,2648,2652,2654,2658,2661,2664,2667,2671,2674,
+2677,2681,2684,2688,2691,2695,2699,2702,2706,2710,2713,2717,
+2721,2724,2729,2732,2736,2741,2744,2748,2753,2757,2761,2765,
+2769,2773,2778,2782,2787,2791,2796,2800,2804,2809,2814,2818,
+2823,2827,2832,2837,2842,2846,2851,2856,2861,2866,2871,2876,
+2881,2887,2892,2897,2902,2907,2912,2918,2923,2929,2934,2939,
+2945,2950,2956,2961,2967,2973,2978,2984,2990,2996,3001,3007,
+3013,3019,3025,3031,3037,3043,3049,3055,3061,3068,3074,3080,
+3087,3093,3099,3106,3112,3119,3125,3132,3139,3145,3151,3158,
+3165,3172,3179,3186,3192,3199,3206,3213,3220,3227,3234,3241,
+3248,3255,3263,3270,3277,3284,3292,3299,3307,3314,3321,3329,
+3337,3344,3352,3359,3367,3375,3382,3390,3398,3406,3414,3422,
+3429,3438,3446,3453,3462,3470,3478,3486,3494,3502,3511,3519,
+3527,3536,3544,3553,3561,3570,3578,3587,3595,3604,3613,3621,
+3630,3639,3647,3657,3666,3675,3684,3693,3702,3711,3720,3729,
+3738,3747,3756,3765,3775,3784,3793,3803,3812,3821,3831,3840,
+3850,3860,3869,3879,3888,3898,3908,3917,3927,3937,3947,3957,
+3967,3976,3987,3997,4006,4017,4027,4037,4047,4057,4067,4078,
+4088,4098,4109,4119,4130,4140,4150,4161,4172,4182,4193,4204,
+4214,4225,4235,4246,4257,4268,4279,4290,4301,4312,4323,4334,
+4345,4356,4367,4378,4389,4400,4412,4423,4434,4445,4457,4468,
+4480,4491,4503,4514,4526,4537,4549,4560,4572,4584,4595,4607,
+4619,4631,4643,4655,4667,4679,4691,4703,4715,4727,4739,4751,
+4763,4775,4788,4800,4812,4824,4836,4849,4861,4874,4886,4899,
+4911,4924,4937,4949,4962,4974,4987,5000,5012,5025,5038,5051,
+5064,5077,5090,5103,5116,5129,5142,5155,5168,5181,5194,5208,
+5221,5234,5247,5261,5274,5287,5301,5314,5328,5341,5355,5368,
+5382,5396,5409,5423,5437,5450,5464,5478,5492,5505,5519,5533,
+5547,5561,5575,5589,5603,5617,5631,5645,5660,5673,5688,5702,
+5716,5731,5745,5759,5774,5788,5803,5817,5831,5846,5860,5875,
+5889,5904,5919,5934,5948,5963,5978,5992,6008,6022,6037,6052,
+6067,6082,6097,6112,6127,6142,6157,6172,6187,6202,6218,6233,
+6248,6263,6279,6294,6310,6325,6340,6356,6371,6387,6402,6418,
+6433,6449,6465,6480,6496,6512,6527,6543,6559,6575,6591,6606,
+6622,6638,6654,6670,6686,6702,6718,6734,6750,6767,6783,6799,
+6815,6831,6847,6864,6880,6896,6912,6929,6946,6963,6979,6996,
+7012,7029,7045,7062,7079,7095,7112,7129,7145,7162,7178,7195,
+7212,7229,7246,7263,7279,7297,7314,7330,7347,7364,7381,7399,
+7416,7433,7450,7467,7484,7502,7519,7536,7553,7570,7588,7605,
+7622,7640,7658,7675,7692,7710,7727,7745,7762,7780,7797,7815,
+7833,7851,7868,7886,7904,7922,7939,7957,7975,7993,8011,8029,
+8047,8064,8082,8100,8118,8136,8155,8173,8191,8209,8227,8245,
+8263,8282,8300,8318,8337,8355,8373,8392,8410,8428,8446,8465,
+8483,8502,8520,8539,8558,8576,8595,8613,8632,8651,8669,8688,
+8707,8725,8744,8763,8782,8801,8819,8838,8857,8876,8895,8914,
+8933,8952,8971,8990,9009,9028,9047,9066,9085,9104,9124,9143,
+9162,9181,9200,9220,9239,9259,9277,9297,9316,9336,9355,9374,
+9394,9414,9433,9452,9472,9492,9511,9531,9550,9570,9590,9609,
+9629,9649,9668,9688,9708,9728,9747,9767,9787,9807,9827,9847,
+9866,9886,9906,9926,9946,9966,9986,10006,10026,10046,10066,10086,
+10107,10127,10147,10167,10187,10207,10227,10248,10268,10288,10309,10329,
+10349,10370,10390,10410,10431,10451,10472,10492,10512,10533,10553,10574,
+10594,10615,10636,10656,10677,10697,10718,10739,10759,10780,10801,10821,
+10842,10863,10883,10904,10925,10946,10967,10987,11009,11029,11050,11071,
+11092,11113,11134,11155,11176,11197,11218,11239,11260,11281,11302,11323,
+11344,11365,11386,11407,11429,11450,11471,11492,11513,11534,11556,11577,
+11598,11619,11641,11662,11684,11705,11726,11748,11769,11790,11812,11833,
+11856,11877,11899,11920,11942,11963,11985,12006,12028,12050,12071,12093,
+12114,12136,12158,12179,12201,12222,12244,12266,12287,12309,12331,12352,
+12374,12396,12418,12440,12461,12483,12505,12527,12549,12571,12592,12614,
+12636,12658,12680,12702,12724,12746,12768,12790,12812,12834,12856,12878,
+12900,12922,12944,12966,12988,13010,13032,13054,13076,13098,13121,13143,
+13165,13187,13209,13231,13254,13276,13298,13320,13343,13365,13387,13410,
+13432,13454,13477,13499,13521,13543,13566,13588,13610,13633,13655,13677,
+13700,13722,13745,13767,13790,13812,13834,13857,13880,13902,13924,13947,
+13970,13992,14014,14037,14060,14082,14105,14127,14150,14172,14195,14217,
+14240,14263,14285,14308,14331,14353,14376,14398,14421,14444,14467,14489,
+14512,14535,14557,14580,14603,14626,14648,14671,14694,14716,14740,14762,
+14785,14808,14831,14854,14876,14899,14922,14945,14968,14990,15013,15036,
+15059,15082,15105,15127,15150,15173,15196,15219,15242,15265,15288,15311,
+15334,15357,15379,15402,15426,15448,15471,15494,15517,15541,15563,15586,
+15609,15632,15655,15678,15701,15724,15747,15770,15793,15817,15839,15862,
+15885,15908,15932,15955,15978,16001,16024,16047,16070,16093,16116,16139,
+16162,16185,16208,16232,16255,16278,16301,16324,16347,16371,16394,16417,
+16440,16463,16486,16509,16532,16555,16579,16602,16625,16648,16671,16694,
+16718,16741,16764,16787,16810,16833,16857,16880,16903,16926,16949,16973,
+16996,17019,17042,17065,17088,17111,17135,17158,17181,17204,17227,17251,
+17274,17297,17320,17344,17367,17390,17413,17436,17460,17483,17506,17529,
+17552,17575,17598,17622,17647,17670,17693,17716,17739,17762,17786,17809,
+17832,17855,17879,17902,17925,17948,17971,17995,18018,18041,18064,18087,
+18110,18134,18157,18180,18203,18226,18250,18273,18296,18319,18342,18366,
+18389,18412,18435,18458,18482,18505,18528,18551,18574,18597,18621,18644,
+18667,18690,18713,18736,18760,18783,18806,18829,18852,18875,18898,18921,
+18944,18968,18991,19014,19037,19060,19083,19106,19129,19152,19175,19199,
+19222,19245,19268,19291,19314,19337,19360,19383,19406,19429,19452,19475,
+19498,19521,19544,19567,19590,19613,19636,19659,19682,19705,19728,19751,
+19774,19797,19820,19843,19866,19889,19912,19935,19958,19981,20004,20027,
+20049,20072,20095,20118,20141,20164,20187,20210,20233,20255,20278,20301,
+20324,20347,20370,20392,20415,20438,20461,20484,20506,20529,20552,20575,
+20598,20620,20643,20666,20689,20711,20734,20757,20779,20802,20825,20848,
+20870,20893,20915,20938,20961,20983,21006,21028,21051,21074,21096,21119,
+21142,21164,21187,21209,21232,21254,21277,21299,21322,21344,21367,21389,
+21412,21434,21457,21479,21502,21524,21546,21569,21591,21614,21636,21659,
+21681,21703,21726,21748,21770,21792,21815,21837,21859,21882,21904,21926,
+21949,21971,21993,22015,22038,22060,22082,22104,22126,22148,22171,22193,
+22215,22237,22259,22281,22303,22325,22347,22369,22391,22413,22436,22457,
+22479,22501,22523,22545,22567,22589,22611,22633,22655,22677,22699,22720,
+22743,22764,22786,22808,22830,22851,22873,22895,22917,22938,22960,22982,
+23003,23025,23047,23068,23090,23112,23134,23155,23177,23198,23220,23242,
+23263,23285,23306,23327,23349,23370,23392,23413,23436,23458,23479,23501,
+23522,23543,23565,23586,23607,23628,23650,23671,23693,23714,23735,23756,
+23778,23799,23820,23841,23862,23883,23904,23926,23946,23968,23989,24010,
+24031,24052,24073,24094,24115,24136,24157,24178,24199,24220,24241,24261,
+24282,24303,24324,24345,24366,24386,24407,24428,24448,24469,24490,24511,
+24531,24552,24572,24593,24614,24634,24655,24675,24696,24717,24737,24758,
+24778,24798,24819,24839,24860,24880,24900,24921,24941,24961,24981,25002,
+25022,25042,25063,25083,25103,25123,25144,25163,25184,25204,25224,25244,
+25264,25284,25304,25324,25344,25364,25384,25404,25424,25444,25463,25483,
+25503,25523,25543,25563,25583,25602,25622,25642,25661,25681,25701,25720,
+25740,25759,25779,25799,25818,25837,25857,25877,25896,25915,25935,25954,
+25974,25993,26012,26032,26051,26070,26089,26109,26128,26147,26166,26185,
+26204,26224,26243,26262,26281,26300,26319,26338,26357,26376,26395,26413,
+26432,26451,26470,26489,26508,26527,26546,26564,26583,26602,26620,26639,
+26658,26676,26695,26714,26732,26750,26769,26787,26806,26824,26843,26861,
+26880,26898,26916,26935,26953,26971,26990,27008,27026,27044,27063,27081,
+27099,27117,27135,27153,27171,27189,27207,27225,27243,27261,27279,27297,
+27314,27332,27350,27368,27386,27403,27421,27439,27456,27474,27491,27509,
+27527,27545,27562,27579,27597,27614,27632,27649,27666,27684,27701,27719,
+27736,27753,27770,27788,27805,27822,27839,27856,27873,27890,27907,27924,
+27942,27959,27975,27992,28009,28026,28043,28060,28077,28093,28110,28127,
+28144,28160,28177,28194,28210,28227,28243,28260,28277,28293,28309,28326,
+28343,28360,28376,28393,28409,28425,28441,28458,28474,28490,28506,28522,
+28538,28554,28570,28586,28603,28618,28634,28650,28666,28682,28698,28714,
+28730,28745,28761,28777,28792,28808,28824,28839,28855,28870,28886,28902,
+28917,28933,28948,28963,28979,28994,29009,29025,29040,29055,29070,29085,
+29101,29116,29131,29146,29161,29176,29191,29206,29221,29236,29251,29266,
+29281,29296,29310,29325,29339,29354,29369,29384,29398,29413,29428,29442,
+29456,29471,29485,29500,29514,29529,29543,29557,29572,29585,29600,29614,
+29628,29642,29657,29670,29685,29699,29713,29727,29741,29754,29768,29782,
+29796,29810,29824,29837,29851,29865,29879,29892,29906,29919,29933,29946,
+29960,29973,29987,30000,30013,30027,30040,30053,30066,30080,30093,30106,
+30119,30132,30145,30158,30171,30185,30198,30210,30223,30236,30249,30262,
+30275,30287,30300,30313,30325,30338,30350,30363,30376,30388,30401,30413,
+30426,30438,30450,30463,30475,30487,30499,30511,30524,30536,30548,30560,
+30572,30584,30596,30608,30620,30632,30644,30655,30668,30679,30691,30703,
+30715,30726,30738,30749,30761,30772,30784,30795,30807,30818,30830,30841,
+30852,30864,30875,30886,30897,30908,30920,30931,30942,30953,30964,30974,
+30986,30997,31007,31018,31029,31040,31051,31061,31072,31083,31093,31104,
+31114,31125,31136,31146,31156,31167,31177,31188,31198,31208,31218,31228,
+31239,31249,31259,31269,31279,31289,31299,31309,31319,31329,31339,31349,
+31359,31368,31378,31388,31397,31407,31417,31426,31436,31445,31455,31464,
+31474,31483,31492,31502,31511,31520,31529,31539,31547,31557,31566,31575,
+31584,31593,31602,31611,31620,31629,31638,31647,31655,31664,31673,31681,
+31690,31699,31707,31716,31724,31733,31741,31750,31758,31766,31775,31783,
+31791,31799,31807,31815,31823,31831,31840,31847,31855,31863,31871,31879,
+31887,31895,31902,31910,31918,31925,31933,31941,31948,31956,31963,31971,
+31978,31985,31993,32000,32008,32015,32022,32029,32036,32043,32051,32057,
+32064,32071,32078,32085,32092,32099,32106,32112,32119,32126,32133,32139,
+32146,32153,32159,32166,32172,32178,32185,32191,32197,32204,32210,32216,
+32222,32229,32235,32241,32247,32253,32259,32265,32271,32277,32282,32288,
+32294,32300,32305,32311,32317,32322,32328,32334,32339,32345,32350,32355,
+32361,32366,32371,32376,32382,32387,32392,32397,32402,32407,32412,32418,
+32422,32427,32432,32437,32442,32447,32451,32456,32461,32465,32470,32474,
+32479,32484,32488,32492,32497,32501,32505,32510,32514,32518,32522,32527,
+32531,32535,32539,32543,32547,32551,32555,32558,32562,32566,32570,32574,
+32577,32581,32585,32588,32592,32595,32599,32602,32605,32609,32612,32616,
+32619,32622,32625,32629,32631,32635,32638,32641,32644,32647,32649,32653,
+32655,32658,32661,32664,32666,32669,32671,32674,32677,32679,32682,32684,
+32687,32689,32691,32694,32696,32698,32700,32702,32705,32707,32709,32711,
+32713,32715,32717,32719,32720,32722,32724,32726,32727,32729,32731,32732,
+32734,32736,32737,32738,32740,32741,32743,32744,32745,32746,32748,32749,
+32750,32751,32752,32753,32754,32755,32756,32757,32758,32759,32760,32760,
+32761,32761,32762,32763,32763,32764,32764,32765,32765,32766,32766,32767,
+32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,32767,
+32767,32767,32767,32767,32767,32766,32766,32765,32765,32764,32764,32763,
+32763,32762,32761,32761,32760,32760,32759,32758,32757,32756,32755,32754,
+32753,32752,32751,32750,32749,32748,32747,32745,32744,32743,32741,32740,
+32738,32737,32736,32734,32732,32731,32729,32728,32726,32724,32722,32720,
+32719,32717,32715,32713,32711,32709,32707,32705,32702,32701,32698,32696,
+32694,32691,32689,32687,32684,32682,32679,32677,32674,32671,32669,32666,
+32664,32661,32658,32655,32653,32650,32647,32644,32641,32638,32635,32632,
+32629,32625,32622,32619,32616,32612,32609,32606,32602,32599,32595,32592,
+32588,32585,32581,32577,32574,32570,32566,32563,32559,32555,32551,32547,
+32543,32539,32535,32531,32527,32523,32519,32514,32510,32506,32502,32497,
+32493,32488,32484,32479,32475,32470,32466,32461,32456,32452,32447,32442,
+32437,32432,32428,32423,32418,32413,32408,32403,32398,32393,32388,32382,
+32377,32372,32366,32361,32356,32350,32345,32340,32334,32328,32323,32317,
+32311,32306,32300,32294,32289,32283,32277,32271,32265,32259,32253,32247,
+32241,32235,32229,32223,32217,32210,32204,32198,32191,32185,32179,32172,
+32166,32160,32153,32146,32140,32133,32126,32120,32113,32106,32100,32093,
+32086,32079,32072,32065,32058,32051,32044,32037,32029,32022,32015,32008,
+32001,31993,31986,31979,31971,31964,31956,31949,31941,31934,31926,31918,
+31911,31903,31895,31887,31880,31872,31864,31856,31848,31840,31832,31824,
+31816,31808,31799,31791,31783,31775,31767,31758,31750,31742,31733,31725,
+31716,31708,31699,31690,31682,31673,31665,31656,31647,31638,31630,31621,
+31611,31602,31594,31584,31576,31566,31557,31548,31539,31530,31521,31511,
+31502,31493,31484,31474,31465,31455,31446,31436,31427,31417,31408,31398,
+31388,31378,31369,31359,31349,31340,31329,31320,31310,31300,31290,31280,
+31270,31260,31250,31239,31229,31219,31209,31198,31188,31178,31167,31157,
+31147,31136,31126,31115,31105,31094,31083,31073,31062,31051,31041,31030,
+31019,31008,30997,30986,30975,30964,30953,30942,30931,30920,30909,30898,
+30887,30876,30864,30853,30842,30830,30819,30807,30796,30785,30773,30762,
+30750,30739,30727,30715,30704,30692,30680,30668,30656,30644,30633,30621,
+30609,30597,30585,30573,30561,30549,30537,30524,30512,30500,30488,30475,
+30463,30451,30439,30426,30414,30402,30389,30376,30364,30351,30339,30326,
+30313,30301,30288,30275,30263,30250,30237,30224,30211,30198,30185,30172,
+30159,30146,30133,30120,30107,30094,30081,30067,30054,30041,30028,30014,
+30001,29988,29974,29961,29947,29933,29920,29906,29893,29879,29866,29852,
+29838,29825,29811,29797,29783,29769,29755,29741,29728,29713,29699,29686,
+29671,29657,29643,29629,29615,29601,29586,29572,29558,29544,29530,29515,
+29500,29486,29472,29457,29443,29428,29414,29399,29385,29370,29355,29340,
+29326,29311,29296,29282,29266,29252,29237,29222,29207,29192,29177,29162,
+29147,29132,29117,29102,29086,29071,29056,29041,29025,29010,28995,28980,
+28964,28949,28934,28918,28903,28887,28871,28856,28840,28825,28809,28793,
+28778,28762,28746,28730,28715,28699,28683,28667,28651,28635,28619,28604,
+28587,28571,28556,28539,28523,28507,28491,28475,28459,28442,28426,28410,
+28393,28377,28361,28345,28327,28310,28294,28278,28261,28244,28228,28211,
+28195,28178,28161,28145,28128,28111,28094,28078,28061,28044,28027,28010,
+27993,27977,27960,27942,27925,27909,27892,27875,27858,27840,27823,27806,
+27789,27772,27754,27737,27719,27702,27685,27668,27650,27633,27616,27598,
+27581,27563,27545,27528,27510,27493,27475,27457,27440,27422,27404,27387,
+27369,27351,27333,27316,27298,27280,27262,27244,27226,27208,27190,27172,
+27154,27136,27118,27100,27081,27063,27045,27027,27009,26991,26973,26954,
+26936,26918,26899,26881,26863,26844,26826,26807,26789,26770,26752,26733,
+26714,26696,26678,26659,26640,26622,26603,26584,26565,26547,26528,26509,
+26490,26472,26453,26434,26415,26396,26377,26358,26339,26320,26301,26282,
+26263,26244,26225,26206,26186,26167,26148,26129,26110,26091,26071,26052,
+26033,26013,25994,25975,25956,25936,25917,25897,25878,25858,25839,25819,
+25800,25780,25761,25741,25721,25702,25682,25662,25643,25623,25603,25583,
+25564,25544,25524,25505,25485,25465,25445,25425,25405,25385,25365,25345,
+25325,25305,25285,25265,25245,25225,25205,25185,25165,25145,25125,25104,
+25084,25064,25044,25023,25003,24983,24963,24942,24922,24902,24881,24861,
+24841,24820,24800,24779,24759,24738,24718,24697,24677,24656,24636,24615,
+24595,24574,24553,24532,24512,24491,24470,24450,24429,24408,24387,24367,
+24346,24325,24304,24283,24263,24242,24221,24200,24179,24158,24137,24116,
+24095,24074,24053,24032,24011,23990,23969,23948,23927,23906,23885,23863,
+23842,23821,23800,23779,23758,23736,23715,23694,23673,23651,23630,23609,
+23587,23566,23544,23523,23502,23480,23459,23438,23415,23393,23372,23351,
+23329,23308,23286,23264,23243,23221,23200,23178,23157,23135,23113,23092,
+23070,23048,23026,23005,22983,22961,22940,22918,22896,22875,22853,22831,
+22809,22787,22766,22743,22722,22700,22678,22656,22635,22612,22591,22569,
+22547,22525,22502,22481,22459,22437,22415,22393,22370,22349,22327,22304,
+22282,22260,22238,22216,22194,22172,22150,22128,22105,22083,22061,22039,
+22016,21994,21972,21950,21928,21906,21883,21861,21839,21816,21794,21772,
+21750,21727,21705,21682,21660,21637,21615,21593,21570,21548,21526,21503,
+21481,21458,21436,21413,21391,21368,21346,21323,21301,21278,21256,21233,
+21211,21188,21166,21143,21120,21098,21075,21052,21030,21007,20985,20962,
+20939,20917,20894,20872,20849,20826,20804,20781,20758,20735,20713,20690,
+20667,20644,20622,20599,20576,20553,20531,20508,20485,20463,20439,20417,
+20394,20371,20348,20325,20303,20280,20257,20234,20211,20188,20165,20143,
+20120,20097,20074,20051,20028,20005,19982,19959,19936,19914,19891,19867,
+19844,19822,19799,19776,19753,19730,19707,19684,19661,19638,19615,19592,
+19569,19546,19523,19500,19476,19453,19431,19408,19385,19361,19338,19315,
+19292,19269,19246,19223,19200,19177,19154,19131,19108,19085,19061,19038,
+19015,18992,18969,18946,18922,18899,18876,18853,18830,18807,18784,18761,
+18738,18714,18691,18668,18645,18622,18599,18576,18552,18529,18506,18483,
+18460,18436,18413,18390,18367,18344,18320,18297,18274,18251,18228,18205,
+18182,18158,18135,18112,18089,18066,18043,18019,17996,17973,17950,17926,
+17903,17880,17857,17833,17810,17787,17764,17741,17718,17695,17671,17648,
+17623,17600,17577,17554,17531,17507,17484,17461,17438,17414,17391,17368,
+17345,17322,17298,17275,17252,17229,17206,17183,17159,17136,17113,17090,
+17067,17044,17020,16997,16974,16951,16927,16904,16881,16858,16835,16811,
+16788,16765,16742,16719,16696,16672,16649,16626,16603,16580,16557,16533,
+16510,16487,16464,16441,16418,16395,16372,16349,16326,16302,16279,16256,
+16233,16210,16187,16164,16141,16118,16094,16071,16048,16025,16002,15979,
+15956,15933,15910,15887,15864,15841,15818,15795,15772,15749,15726,15703,
+15679,15657,15634,15611,15588,15565,15542,15519,15496,15473,15450,15427,
+15404,15381,15358,15335,15312,15289,15266,15243,15221,15198,15175,15152,
+15129,15106,15083,15060,15037,15015,14992,14969,14946,14923,14900,14878,
+14855,14832,14809,14786,14764,14741,14718,14695,14673,14650,14627,14604,
+14582,14559,14536,14513,14491,14468,14445,14423,14400,14377,14355,14332,
+14309,14287,14264,14241,14219,14196,14174,14151,14129,14106,14084,14061,
+14038,14016,13993,13971,13948,13926,13904,13881,13858,13836,13814,13791,
+13769,13746,13723,13701,13679,13657,13634,13612,13590,13567,13545,13522,
+13500,13478,13455,13433,13411,13389,13366,13344,13322,13300,13278,13255,
+13233,13211,13188,13166,13144,13122,13100,13078,13055,13034,13012,12989,
+12967,12945,12923,12901,12879,12857,12835,12813,12791,12769,12747,12725,
+12703,12682,12659,12638,12616,12594,12572,12550,12528,12507,12484,12463,
+12441,12419,12397,12376,12354,12332,12310,12289,12267,12245,12224,12202,
+12180,12159,12137,12116,12094,12072,12051,12029,12008,11986,11965,11943,
+11922,11900,11879,11857,11834,11813,11792,11770,11749,11727,11706,11685,
+11664,11642,11621,11599,11578,11557,11536,11515,11493,11472,11451,11430,
+11409,11388,11366,11346,11324,11303,11282,11261,11240,11219,11198,11177,
+11156,11135,11114,11093,11072,11052,11031,11010,10989,10968,10947,10926,
+10906,10885,10864,10843,10823,10802,10781,10761,10740,10719,10699,10678,
+10657,10637,10616,10596,10575,10555,10534,10514,10493,10473,10452,10432,
+10412,10391,10371,10351,10330,10310,10290,10270,10249,10229,10209,10188,
+10168,10148,10128,10108,10088,10068,10047,10028,10007,9987,9968,9947,
+9927,9908,9888,9867,9848,9828,9808,9788,9768,9748,9729,9709,
+9689,9669,9650,9630,9610,9591,9571,9552,9532,9512,9493,9473,
+9454,9434,9415,9395,9376,9356,9337,9318,9298,9279,9259,9240,
+9221,9202,9182,9163,9144,9125,9106,9086,9067,9048,9029,9010,
+8991,8972,8953,8934,8915,8896,8877,8858,8839,8820,8801,8783,
+8764,8745,8727,8708,8689,8670,8652,8633,8615,8596,8577,8559,
+8540,8522,8503,8485,8466,8448,8429,8411,8392,8374,8356,8338,
+8319,8301,8283,8265,8246,8228,8210,8192,8174,8156,8138,8120,
+8102,8084,8066,8048,8030,8012,7994,7976,7958,7941,7923,7905,
+7887,7869,7851,7834,7816,7799,7781,7763,7746,7728,7711,7694,
+7676,7658,7641,7624,7606,7589,7572,7554,7537,7520,7502,7485,
+7468,7451,7434,7417,7399,7382,7365,7348,7332,7315,7297,7281,
+7264,7247,7230,7213,7196,7180,7163,7146,7129,7113,7096,7080,
+7063,7046,7030,7013,6997,6980,6964,6948,6930,6913,6897,6881,
+6864,6848,6832,6816,6800,6784,6768,6751,6735,6719,6703,6687,
+6671,6655,6639,6623,6607,6592,6575,6560,6544,6528,6513,6497,
+6481,6466,6450,6434,6419,6403,6388,6372,6357,6341,6326,6310,
+6295,6280,6264,6249,6234,6219,6203,6188,6173,6158,6143,6128,
+6113,6098,6083,6068,6053,6038,6023,6009,5993,5979,5964,5949,
+5935,5920,5905,5890,5876,5861,5847,5832,5818,5804,5789,5775,
+5760,5746,5732,5717,5703,5689,5674,5660,5646,5632,5618,5604,
+5590,5576,5562,5548,5534,5520,5506,5492,5479,5465,5451,5437,
+5424,5410,5396,5383,5369,5355,5342,5329,5315,5302,5288,5275,
+5262,5248,5235,5221,5209,5195,5182,5169,5156,5143,5130,5117,
+5103,5090,5077,5065,5052,5039,5026,5013,5001,4988,4975,4962,
+4950,4937,4925,4912,4900,4887,4875,4862,4850,4837,4825,4813,
+4800,4788,4776,4764,4752,4740,4728,4716,4704,4692,4680,4668,
+4656,4644,4632,4620,4608,4596,4584,4573,4561,4549,4538,4526,
+4515,4503,4492,4481,4469,4457,4446,4435,4424,4412,4401,4390,
+4379,4367,4356,4345,4334,4323,4312,4301,4290,4279,4269,4258,
+4247,4236,4225,4215,4204,4193,4183,4172,4162,4151,4141,4130,
+4120,4109,4099,4089,4078,4068,4058,4048,4037,4028,4018,4007,
+3997,3987,3977,3967,3958,3947,3938,3928,3918,3909,3898,3889,
+3879,3870,3860,3850,3841,3831,3822,3813,3803,3794,3784,3775,
+3766,3757,3747,3738,3729,3720,3711,3702,3693,3684,3675,3666,
+3657,3648,3639,3631,3622,3613,3604,3596,3587,3579,3570,3561,
+3553,3545,3536,3528,3519,3511,3503,3495,3487,3478,3470,3462,
+3454,3446,3438,3430,3422,3414,3406,3398,3391,3383,3375,3368,
+3360,3352,3344,3337,3330,3322,3314,3307,3300,3292,3285,3278,
+3271,3263,3256,3249,3242,3235,3228,3221,3213,3206,3199,3193,
+3186,3179,3172,3165,3159,3152,3145,3139,3132,3126,3119,3113,
+3106,3100,3093,3087,3081,3074,3068,3062,3056,3050,3043,3037,
+3031,3025,3019,3013,3008,3002,2996,2990,2984,2979,2973,2967,
+2962,2956,2951,2945,2940,2934,2929,2923,2918,2913,2907,2902,
+2897,2892,2887,2881,2876,2871,2867,2862,2856,2852,2847,2842,
+2837,2832,2828,2823,2819,2814,2809,2805,2800,2796,2791,2787,
+2783,2778,2774,2770,2766,2761,2757,2753,2749,2745,2741,2736,
+2733,2729,2725,2721,2717,2713,2710,2706,2702,2699,2695,2692,
+2688,2685,2681,2678,2674,2671,2668,2664,2661,2658,2655,2652,
+2648,2646,2642,2640,2636,2634,2631,2628,2625,2622,2619,2616,
+2614,2611,2609,2606,2604,2601,2598,2596,2594,2592,2589,2587,
+2585,2582,2580,2578,2576,2574,2572,2570,2568,2566,2564,2562,
+2560,2558,2556,2555,2553,2551,2550,2548,2547,2545,2544,2542,
+2541,2539,2538,2537,2536,2534,2533,2532,2531,2530,2529,2528,
+2527,2526,2525,2524,2523,2522,2522,2521,2520,2520,2519,2518,
+2518,2517,2517,2516,2516,2515,2515,2515,2514,2514,2514,2514,
+2514,2514,2514,2514};
+const int32_t hamming_2048 [] = {2514,2514,2514,2514,2515,2515,2516,2517,2518,2520,2521,2522,
+2524,2526,2528,2530,2532,2534,2537,2539,2542,2545,2548,2551,
+2555,2558,2562,2566,2569,2574,2578,2582,2586,2591,2596,2601,
+2606,2611,2616,2622,2628,2633,2639,2645,2652,2658,2664,2671,
+2677,2684,2691,2699,2706,2713,2721,2729,2736,2744,2753,2761,
+2769,2778,2787,2796,2805,2814,2823,2832,2842,2852,2862,2871,
+2881,2892,2902,2913,2923,2934,2945,2956,2967,2979,2990,3002,
+3013,3025,3037,3050,3062,3074,3087,3100,3113,3126,3139,3152,
+3165,3179,3193,3206,3221,3235,3249,3263,3278,3292,3307,3322,
+3337,3352,3368,3383,3398,3414,3430,3446,3462,3478,3495,3511,
+3528,3545,3561,3579,3596,3613,3631,3648,3666,3684,3702,3720,
+3738,3757,3775,3794,3813,3831,3850,3870,3889,3909,3928,3947,
+3967,3987,4007,4028,4048,4068,4089,4109,4130,4151,4172,4193,
+4215,4236,4258,4279,4301,4323,4345,4367,4390,4412,4435,4457,
+4481,4503,4526,4549,4573,4596,4620,4644,4668,4692,4716,4740,
+4764,4788,4813,4837,4862,4887,4912,4937,4962,4988,5013,5039,
+5065,5091,5117,5143,5170,5196,5222,5249,5275,5302,5330,5356,
+5384,5411,5438,5466,5493,5521,5549,5576,5605,5633,5661,5690,
+5718,5747,5775,5804,5833,5862,5891,5921,5950,5979,6009,6039,
+6069,6099,6129,6159,6189,6220,6250,6281,6311,6342,6373,6404,
+6435,6467,6498,6529,6561,6593,6624,6656,6688,6720,6752,6785,
+6817,6849,6882,6915,6948,6981,7014,7047,7080,7114,7147,7181,
+7214,7248,7282,7315,7350,7384,7418,7452,7486,7521,7556,7590,
+7625,7659,7694,7730,7765,7800,7835,7870,7906,7941,7977,8013,
+8049,8085,8121,8157,8193,8230,8266,8302,8338,8375,8412,8449,
+8486,8523,8560,8597,8634,8672,8709,8747,8784,8822,8860,8898,
+8935,8973,9011,9049,9088,9126,9164,9203,9243,9281,9320,9359,
+9397,9437,9475,9515,9554,9593,9632,9672,9711,9751,9791,9830,
+9870,9910,9950,9990,10030,10070,10110,10150,10191,10231,10272,10312,
+10353,10394,10435,10475,10516,10557,10598,10639,10681,10722,10763,10805,
+10846,10888,10929,10971,11012,11054,11096,11138,11180,11222,11264,11306,
+11348,11390,11432,11475,11517,11560,11602,11645,11688,11730,11773,11816,
+11860,11903,11946,11989,12032,12075,12118,12161,12205,12248,12291,12335,
+12378,12422,12466,12509,12553,12597,12640,12684,12728,12772,12816,12860,
+12904,12948,12992,13037,13080,13125,13169,13213,13258,13302,13347,13392,
+13436,13481,13525,13570,13615,13659,13704,13749,13794,13839,13884,13928,
+13974,14018,14064,14109,14154,14199,14244,14289,14335,14380,14426,14471,
+14516,14562,14607,14653,14699,14745,14791,14836,14882,14927,14973,15019,
+15065,15110,15156,15202,15248,15294,15339,15385,15431,15477,15523,15569,
+15615,15661,15707,15753,15799,15845,15891,15938,15984,16030,16076,16122,
+16168,16214,16261,16307,16353,16399,16445,16492,16538,16584,16630,16677,
+16723,16769,16816,16862,16909,16955,17001,17048,17094,17141,17187,17233,
+17279,17326,17372,17419,17465,17512,17558,17604,17653,17699,17745,17791,
+17838,17884,17931,17977,18024,18070,18116,18163,18209,18255,18302,18348,
+18394,18441,18487,18534,18580,18626,18673,18719,18765,18811,18858,18904,
+18950,18996,19042,19089,19135,19181,19227,19273,19319,19366,19412,19458,
+19504,19550,19596,19642,19688,19734,19780,19826,19872,19918,19963,20010,
+20055,20101,20147,20192,20238,20284,20330,20375,20421,20467,20512,20558,
+20605,20650,20696,20741,20787,20832,20877,20922,20968,21013,21058,21103,
+21148,21194,21239,21284,21329,21374,21419,21464,21509,21553,21598,21643,
+21688,21732,21777,21822,21866,21911,21955,22000,22045,22089,22133,22177,
+22222,22266,22310,22354,22398,22442,22486,22530,22574,22618,22662,22706,
+22749,22793,22836,22880,22924,22967,23010,23054,23097,23140,23183,23227,
+23270,23313,23356,23399,23443,23486,23529,23571,23614,23657,23699,23742,
+23784,23826,23869,23911,23953,23995,24037,24079,24121,24163,24205,24247,
+24289,24331,24372,24414,24455,24496,24538,24579,24620,24661,24702,24743,
+24784,24825,24866,24907,24947,24988,25029,25069,25109,25150,25190,25230,
+25270,25310,25350,25390,25430,25470,25510,25549,25589,25628,25667,25707,
+25746,25785,25824,25863,25902,25941,25980,26018,26058,26097,26135,26173,
+26212,26250,26288,26326,26364,26402,26440,26477,26515,26552,26590,26627,
+26665,26702,26739,26776,26813,26850,26887,26923,26960,26997,27033,27069,
+27105,27142,27178,27214,27250,27286,27321,27357,27392,27428,27463,27498,
+27533,27569,27604,27638,27673,27708,27742,27777,27811,27846,27880,27914,
+27948,27982,28015,28050,28083,28116,28150,28183,28217,28249,28283,28315,
+28350,28382,28415,28447,28480,28512,28544,28576,28609,28640,28672,28704,
+28736,28767,28798,28830,28861,28892,28923,28954,28984,29015,29046,29076,
+29106,29137,29167,29197,29227,29256,29286,29316,29345,29374,29404,29433,
+29462,29491,29519,29548,29577,29605,29633,29662,29690,29718,29746,29774,
+29801,29829,29856,29884,29911,29938,29965,29992,30018,30045,30072,30098,
+30124,30150,30176,30202,30229,30254,30280,30306,30331,30356,30381,30406,
+30431,30456,30480,30505,30529,30553,30577,30601,30625,30649,30673,30696,
+30720,30743,30766,30789,30812,30835,30857,30880,30902,30924,30946,30968,
+30991,31012,31034,31055,31077,31098,31119,31140,31161,31182,31203,31223,
+31243,31263,31284,31304,31323,31343,31363,31382,31402,31421,31440,31459,
+31478,31496,31515,31533,31552,31570,31588,31606,31624,31642,31659,31677,
+31694,31711,31728,31745,31762,31778,31794,31811,31827,31843,31859,31875,
+31890,31906,31921,31937,31951,31967,31981,31996,32010,32025,32039,32053,
+32068,32082,32095,32109,32122,32136,32149,32162,32175,32188,32200,32213,
+32225,32238,32250,32262,32274,32285,32297,32308,32319,32330,32341,32352,
+32363,32374,32384,32394,32405,32415,32425,32434,32444,32454,32463,32472,
+32481,32490,32499,32508,32516,32525,32533,32541,32549,32557,32564,32572,
+32579,32587,32593,32600,32607,32614,32620,32627,32633,32639,32645,32651,
+32657,32662,32668,32673,32678,32683,32688,32692,32697,32701,32706,32710,
+32714,32718,32721,32725,32728,32731,32735,32738,32741,32743,32746,32748,
+32750,32753,32755,32756,32758,32760,32761,32762,32764,32765,32766,32766,
+32767,32767,32767,32767,32767,32767,32767,32767,32766,32766,32765,32764,
+32762,32761,32760,32758,32756,32755,32753,32750,32749,32746,32743,32741,
+32738,32735,32731,32728,32725,32721,32718,32714,32710,32706,32701,32697,
+32693,32688,32683,32678,32673,32668,32662,32657,32651,32645,32639,32633,
+32627,32621,32614,32607,32600,32593,32587,32579,32572,32564,32557,32549,
+32541,32533,32525,32516,32508,32499,32491,32482,32472,32463,32454,32444,
+32435,32425,32415,32405,32395,32384,32374,32364,32352,32342,32331,32320,
+32308,32297,32286,32274,32262,32250,32238,32226,32213,32201,32188,32175,
+32162,32149,32136,32123,32109,32095,32082,32068,32054,32040,32026,32011,
+31997,31982,31967,31952,31937,31922,31906,31891,31875,31859,31843,31828,
+31811,31795,31779,31762,31745,31728,31711,31694,31677,31660,31642,31624,
+31606,31588,31570,31552,31534,31516,31497,31478,31459,31440,31421,31402,
+31383,31363,31344,31324,31304,31284,31264,31244,31223,31203,31182,31161,
+31141,31120,31099,31077,31056,31035,31013,30991,30969,30947,30925,30903,
+30880,30858,30835,30812,30790,30767,30744,30720,30697,30674,30650,30626,
+30602,30578,30554,30530,30505,30481,30457,30432,30407,30382,30357,30331,
+30307,30281,30255,30230,30203,30177,30151,30125,30099,30072,30046,30019,
+29993,29966,29939,29911,29885,29857,29830,29802,29774,29747,29719,29691,
+29663,29634,29606,29578,29549,29520,29492,29463,29434,29404,29375,29346,
+29317,29287,29257,29228,29198,29168,29138,29107,29077,29047,29016,28985,
+28955,28924,28893,28862,28831,28799,28768,28736,28705,28673,28641,28610,
+28577,28545,28513,28481,28448,28416,28383,28351,28317,28284,28251,28218,
+28184,28151,28117,28084,28050,28017,27983,27949,27915,27881,27846,27812,
+27778,27743,27709,27674,27639,27605,27569,27534,27499,27464,27429,27393,
+27358,27322,27286,27250,27215,27179,27143,27106,27070,27034,26997,26961,
+26925,26888,26851,26814,26777,26740,26703,26666,26629,26591,26554,26516,
+26479,26441,26403,26365,26327,26289,26251,26213,26175,26136,26098,26059,
+26020,25981,25942,25903,25864,25825,25786,25747,25708,25668,25629,25590,
+25550,25511,25471,25431,25391,25352,25312,25271,25231,25191,25151,25111,
+25070,25030,24989,24949,24908,24867,24826,24786,24745,24704,24662,24621,
+24580,24539,24498,24456,24415,24373,24332,24290,24248,24206,24165,24123,
+24081,24039,23997,23954,23912,23870,23828,23785,23743,23700,23658,23615,
+23573,23530,23487,23444,23400,23357,23314,23271,23228,23185,23142,23098,
+23055,23012,22968,22925,22881,22838,22794,22750,22707,22663,22619,22575,
+22532,22488,22443,22400,22356,22311,22267,22223,22179,22135,22090,22046,
+22001,21957,21913,21868,21823,21779,21734,21689,21645,21600,21555,21510,
+21465,21420,21375,21330,21285,21240,21195,21150,21105,21060,21015,20969,
+20924,20878,20833,20788,20742,20697,20652,20606,20559,20514,20468,20422,
+20377,20331,20285,20240,20194,20148,20102,20057,20011,19965,19919,19873,
+19827,19782,19735,19689,19644,19597,19551,19506,19459,19413,19367,19321,
+19275,19229,19182,19136,19090,19044,18998,18952,18905,18859,18813,18766,
+18720,18674,18627,18581,18535,18489,18442,18396,18350,18303,18257,18211,
+18164,18118,18071,18025,17978,17932,17886,17839,17793,17747,17700,17654,
+17606,17560,17513,17467,17420,17374,17328,17281,17235,17188,17142,17096,
+17049,17003,16956,16910,16864,16817,16771,16725,16678,16632,16586,16539,
+16493,16447,16401,16354,16308,16262,16216,16170,16124,16077,16031,15985,
+15939,15893,15847,15800,15755,15709,15662,15616,15571,15524,15479,15432,
+15387,15341,15295,15249,15204,15157,15112,15066,15020,14975,14929,14883,
+14838,14792,14746,14701,14654,14608,14563,14518,14472,14427,14382,14336,
+14291,14246,14200,14156,14110,14065,14020,13975,13930,13885,13840,13795,
+13750,13705,13661,13616,13571,13526,13482,13437,13393,13348,13304,13259,
+13215,13170,13126,13082,13038,12994,12949,12905,12861,12817,12773,12730,
+12685,12642,12598,12554,12510,12467,12423,12380,12336,12293,12249,12206,
+12163,12120,12076,12033,11990,11947,11904,11861,11817,11774,11732,11689,
+11646,11604,11561,11519,11476,11434,11392,11349,11307,11265,11223,11181,
+11139,11097,11055,11014,10972,10930,10889,10847,10806,10764,10723,10682,
+10641,10600,10558,10517,10477,10436,10395,10354,10314,10273,10233,10192,
+10152,10112,10071,10031,9991,9951,9911,9872,9831,9792,9752,9713,
+9673,9634,9595,9555,9516,9477,9438,9399,9360,9321,9283,9244,
+9204,9166,9127,9089,9051,9012,8975,8936,8898,8861,8823,8785,
+8747,8710,8673,8635,8598,8561,8524,8487,8450,8413,8376,8340,
+8303,8267,8230,8194,8158,8122,8086,8050,8014,7978,7943,7907,
+7872,7836,7801,7766,7730,7695,7661,7626,7591,7556,7522,7487,
+7453,7419,7385,7351,7316,7283,7249,7215,7182,7148,7115,7081,
+7048,7015,6982,6949,6916,6883,6851,6818,6786,6753,6721,6689,
+6657,6625,6593,6562,6530,6499,6467,6436,6405,6374,6343,6312,
+6282,6251,6220,6190,6160,6130,6100,6070,6040,6010,5980,5951,
+5922,5892,5863,5834,5805,5776,5748,5719,5691,5662,5634,5606,
+5577,5550,5522,5494,5467,5439,5412,5384,5357,5330,5303,5276,
+5250,5223,5197,5170,5144,5118,5092,5066,5040,5014,4989,4963,
+4938,4913,4888,4863,4838,4813,4789,4764,4740,4716,4692,4668,
+4644,4620,4597,4574,4550,4527,4504,4481,4458,4436,4413,4391,
+4368,4346,4324,4302,4280,4258,4237,4216,4194,4173,4152,4131,
+4110,4090,4069,4048,4028,4008,3988,3968,3948,3928,3909,3890,
+3870,3851,3832,3813,3795,3776,3757,3739,3721,3703,3685,3667,
+3649,3631,3614,3597,3579,3562,3545,3528,3512,3495,3479,3463,
+3446,3430,3415,3399,3383,3368,3353,3338,3322,3308,3293,3278,
+3264,3249,3235,3221,3207,3193,3180,3166,3152,3139,3126,3113,
+3100,3087,3075,3062,3050,3038,3026,3014,3002,2991,2979,2968,
+2957,2946,2935,2924,2913,2903,2892,2882,2872,2862,2852,2842,
+2833,2823,2814,2805,2796,2787,2778,2770,2761,2753,2745,2736,
+2729,2721,2713,2706,2699,2692,2685,2678,2671,2664,2658,2652,
+2646,2640,2634,2628,2622,2616,2611,2606,2601,2596,2592,2587,
+2582,2578,2574,2570,2566,2562,2558,2555,2551,2548,2545,2542,
+2539,2537,2534,2532,2530,2528,2526,2524,2522,2521,2520,2518,
+2517,2516,2515,2515,2514,2514,2514,2514};
+const int32_t hamming_1024 [] = {2514,2514,2515,2516,2518,2521,2524,2528,2532,2537,2542,2548,
+2555,2562,2569,2578,2587,2596,2606,2616,2628,2640,2652,2664,
+2678,2692,2706,2721,2736,2753,2770,2787,2805,2823,2842,2862,
+2882,2903,2924,2946,2968,2991,3014,3038,3062,3087,3113,3139,
+3166,3193,3221,3250,3278,3308,3338,3368,3399,3431,3463,3496,
+3529,3563,3597,3632,3668,3703,3740,3777,3814,3852,3890,3929,
+3969,4009,4049,4090,4132,4174,4216,4259,4303,4348,4392,4437,
+4482,4529,4575,4622,4670,4718,4766,4815,4865,4914,4965,5016,
+5068,5120,5172,5225,5278,5332,5386,5441,5496,5552,5607,5664,
+5721,5778,5836,5894,5954,6013,6073,6133,6193,6254,6315,6377,
+6439,6502,6565,6628,6692,6756,6821,6886,6953,7019,7085,7152,
+7219,7286,7354,7422,7490,7560,7629,7699,7769,7839,7911,7982,
+8055,8126,8199,8272,8344,8418,8492,8566,8640,8715,8790,8865,
+8941,9017,9094,9170,9249,9326,9404,9482,9560,9639,9717,9797,
+9876,9956,10036,10117,10197,10278,10360,10441,10524,10606,10688,10771,
+10854,10937,11020,11104,11188,11272,11356,11441,11525,11610,11696,11781,
+11868,11954,12040,12126,12213,12300,12387,12474,12561,12648,12736,12824,
+12912,13001,13089,13177,13268,13356,13446,13535,13624,13714,13804,13893,
+13983,14073,14164,14254,14345,14435,14526,14617,14710,14800,14892,14983,
+15075,15166,15258,15349,15441,15533,15625,15717,15809,15902,15993,16086,
+16180,16272,16365,16457,16550,16642,16735,16828,16920,17013,17105,17198,
+17291,17384,17477,17570,17664,17757,17850,17942,18035,18128,18221,18314,
+18406,18499,18591,18684,18777,18869,18962,19054,19148,19240,19332,19425,
+19517,19609,19701,19793,19885,19976,20068,20160,20251,20342,20434,20525,
+20618,20709,20799,20890,20980,21071,21161,21251,21341,21431,21522,21611,
+21701,21790,21879,21968,22058,22147,22236,22324,22412,22500,22588,22675,
+22763,22850,22937,23024,23110,23197,23283,23369,23456,23542,23628,23712,
+23797,23882,23966,24051,24134,24218,24302,24385,24468,24551,24633,24715,
+24798,24880,24961,25042,25123,25204,25284,25364,25444,25523,25602,25681,
+25759,25837,25915,25993,26071,26148,26225,26301,26377,26453,26528,26603,
+26678,26752,26826,26899,26973,27045,27118,27190,27263,27334,27406,27476,
+27546,27617,27686,27755,27824,27893,27960,28028,28096,28163,28229,28295,
+28362,28427,28492,28556,28621,28684,28747,28810,28873,28935,28996,29057,
+29118,29178,29238,29297,29357,29416,29474,29531,29588,29645,29701,29757,
+29813,29867,29921,29976,30029,30082,30135,30187,30239,30290,30341,30391,
+30441,30490,30539,30587,30635,30682,30729,30775,30821,30866,30911,30956,
+31000,31043,31086,31128,31170,31211,31252,31293,31332,31372,31410,31448,
+31486,31523,31559,31596,31632,31667,31701,31735,31769,31802,31834,31866,
+31897,31928,31958,31988,32017,32045,32074,32101,32129,32155,32181,32206,
+32231,32255,32279,32302,32324,32346,32368,32389,32409,32429,32449,32467,
+32485,32503,32520,32537,32552,32568,32582,32597,32611,32623,32636,32648,
+32659,32670,32680,32690,32699,32708,32716,32723,32730,32736,32742,32747,
+32752,32755,32759,32762,32764,32766,32767,32767,32767,32767,32766,32764,
+32762,32759,32755,32752,32747,32742,32737,32730,32723,32716,32708,32699,
+32690,32680,32670,32659,32648,32636,32623,32611,32597,32583,32568,32553,
+32537,32521,32503,32486,32467,32449,32430,32410,32389,32368,32347,32325,
+32302,32279,32256,32232,32207,32181,32155,32129,32101,32074,32046,32017,
+31988,31959,31928,31898,31866,31835,31802,31769,31736,31702,31667,31632,
+31596,31560,31523,31486,31449,31411,31372,31333,31293,31253,31212,31171,
+31129,31087,31044,31001,30956,30912,30867,30822,30776,30730,30683,30636,
+30588,30540,30491,30442,30392,30342,30291,30240,30188,30136,30083,30030,
+29976,29922,29868,29813,29758,29702,29646,29589,29532,29475,29416,29358,
+29298,29239,29179,29119,29058,28997,28935,28874,28811,28748,28685,28622,
+28557,28493,28428,28363,28296,28230,28164,28097,28029,27962,27894,27825,
+27756,27687,27617,27548,27477,27406,27335,27264,27191,27119,27046,26973,
+26901,26827,26753,26678,26604,26529,26454,26378,26302,26226,26149,26072,
+25994,25917,25839,25761,25682,25603,25524,25445,25365,25285,25205,25125,
+25044,24963,24881,24800,24717,24634,24552,24469,24386,24303,24220,24136,
+24052,23968,23883,23799,23714,23628,23543,23458,23370,23285,23198,23112,
+23025,22938,22851,22764,22677,22589,22501,22413,22325,22237,22148,22060,
+21969,21880,21791,21702,21612,21523,21433,21343,21253,21163,21072,20982,
+20891,20801,20710,20619,20526,20435,20344,20252,20161,20070,19978,19886,
+19795,19702,19610,19518,19426,19334,19242,19150,19055,18963,18871,18778,
+18686,18593,18500,18408,18315,18222,18129,18037,17944,17851,17758,17665,
+17571,17478,17386,17293,17200,17107,17015,16922,16829,16736,16644,16551,
+16459,16366,16274,16181,16088,15995,15903,15811,15719,15626,15535,15443,
+15351,15259,15167,15076,14985,14893,14802,14711,14619,14528,14437,14346,
+14256,14165,14075,13985,13895,13805,13715,13626,13537,13447,13358,13269,
+13179,13090,13002,12914,12826,12737,12650,12562,12475,12388,12301,12214,
+12128,12041,11955,11869,11782,11697,11611,11527,11442,11357,11273,11189,
+11105,11022,10938,10855,10772,10690,10607,10525,10442,10361,10280,10198,
+10118,10037,9957,9878,9798,9719,9640,9561,9483,9405,9327,9250,
+9172,9095,9018,8942,8867,8791,8716,8641,8567,8493,8419,8345,
+8272,8200,8127,8055,7983,7911,7841,7770,7700,7630,7561,7492,
+7423,7355,7287,7219,7153,7086,7020,6954,6887,6822,6757,6693,
+6629,6566,6503,6440,6378,6316,6255,6194,6134,6074,6014,5955,
+5895,5837,5779,5721,5665,5608,5552,5497,5442,5387,5333,5279,
+5226,5173,5120,5069,5017,4966,4915,4865,4816,4767,4718,4670,
+4623,4576,4529,4483,4438,4393,4348,4304,4260,4217,4174,4132,
+4090,4050,4009,3969,3930,3891,3852,3814,3777,3740,3704,3668,
+3632,3597,3563,3530,3496,3464,3432,3400,3369,3338,3308,3279,
+3250,3222,3194,3167,3139,3114,3088,3063,3038,3014,2991,2968,
+2946,2924,2903,2882,2862,2843,2824,2805,2787,2770,2753,2737,
+2721,2706,2692,2678,2664,2652,2640,2628,2617,2606,2596,2587,
+2578,2570,2562,2555,2548,2542,2537,2532,2528,2524,2521,2518,
+2516,2515,2514,2514};
+const int32_t hamming_512 [] = {2514,2515,2518,2524,2532,2542,2555,2570,2587,2606,2628,2652,
+2678,2706,2737,2770,2806,2843,2882,2924,2969,3015,3064,3114,
+3168,3223,3280,3339,3401,3465,3531,3599,3669,3742,3816,3892,
+3972,4052,4135,4219,4307,4396,4486,4579,4674,4770,4869,4969,
+5073,5177,5283,5391,5502,5613,5727,5842,5960,6079,6200,6322,
+6447,6573,6700,6829,6961,7093,7227,7362,7500,7639,7779,7920,
+8064,8209,8355,8502,8652,8801,8953,9106,9261,9416,9572,9730,
+9890,10050,10211,10373,10538,10703,10868,11034,11203,11372,11541,11712,
+11884,12056,12229,12403,12579,12754,12930,13107,13286,13464,13643,13822,
+14003,14184,14365,14546,14729,14912,15095,15278,15463,15647,15831,16015,
+16201,16386,16571,16756,16943,17129,17315,17500,17687,17873,18058,18244,
+18431,18616,18801,18986,19173,19357,19542,19725,19910,20094,20277,20459,
+20643,20825,21006,21187,21368,21548,21727,21906,22085,22262,22438,22614,
+22790,22964,23138,23310,23483,23654,23824,23993,24162,24329,24495,24660,
+24825,24988,25150,25310,25471,25629,25786,25942,26098,26251,26403,26554,
+26704,26852,26999,27144,27289,27431,27572,27711,27850,27986,28121,28254,
+28386,28516,28644,28771,28897,29020,29141,29261,29380,29496,29610,29723,
+29835,29944,30051,30156,30260,30361,30461,30559,30655,30749,30840,30930,
+31018,31104,31188,31269,31349,31427,31502,31576,31647,31716,31783,31848,
+31911,31972,32030,32086,32141,32192,32242,32289,32335,32378,32419,32457,
+32494,32528,32560,32589,32617,32642,32665,32685,32703,32719,32733,32744,
+32754,32761,32765,32767,32767,32765,32761,32754,32744,32733,32719,32704,
+32685,32665,32642,32617,32589,32560,32528,32494,32458,32419,32378,32335,
+32290,32242,32193,32141,32087,32030,31972,31912,31848,31784,31717,31648,
+31576,31503,31427,31350,31270,31188,31105,31019,30931,30841,30749,30655,
+30559,30462,30362,30261,30157,30052,29945,29836,29724,29611,29497,29381,
+29262,29142,29021,28898,28772,28646,28517,28387,28255,28122,27987,27851,
+27712,27573,27432,27290,27145,27000,26853,26705,26555,26404,26252,26099,
+25943,25788,25631,25472,25312,25151,24989,24826,24661,24496,24331,24163,
+23994,23825,23655,23484,23311,23139,22966,22791,22615,22439,22263,22086,
+21907,21728,21549,21370,21188,21007,20826,20644,20461,20278,20095,19912,
+19727,19543,19359,19174,18988,18803,18617,18432,18245,18060,17874,17689,
+17502,17316,17130,16945,16758,16573,16388,16203,16016,15832,15648,15464,
+15279,15096,14913,14731,14548,14366,14185,14005,13823,13644,13465,13287,
+13108,12931,12755,12580,12404,12231,12057,11885,11713,11543,11373,11205,
+11036,10869,10704,10540,10375,10212,10051,9891,9731,9573,9417,9262,
+9107,8954,8803,8653,8503,8356,8210,8066,7922,7780,7640,7502,
+7363,7228,7094,6962,6830,6701,6574,6448,6323,6201,6080,5961,
+5843,5728,5614,5503,5392,5284,5178,5074,4970,4870,4771,4675,
+4579,4487,4396,4307,4220,4135,4053,3972,3893,3817,3742,3670,
+3600,3531,3466,3402,3340,3280,3223,3168,3115,3064,3015,2969,
+2925,2883,2843,2806,2770,2737,2707,2678,2652,2628,2606,2587,
+2570,2555,2543,2532,2524,2518,2515,2514};
+const int32_t hann_8192 [] = {1,1,1,1,1,1,1,1,1,1,1,1,
+1,1,1,2,2,2,2,2,2,3,3,3,
+3,4,4,4,4,5,5,5,5,6,6,6,
+7,7,7,8,8,9,9,9,10,10,11,11,
+12,12,13,13,14,14,15,15,16,16,17,17,
+18,18,19,20,20,21,21,22,23,23,24,25,
+25,26,27,28,28,29,30,31,31,32,33,34,
+34,35,36,37,38,39,40,40,41,42,43,44,
+45,46,47,48,49,50,51,52,53,54,55,56,
+57,58,59,60,61,62,63,64,65,66,68,69,
+70,71,72,73,75,76,77,78,79,81,82,83,
+84,86,87,88,90,91,92,94,95,96,98,99,
+100,102,103,105,106,107,109,110,112,113,115,116,
+118,119,121,122,124,125,127,128,130,132,133,135,
+136,138,140,141,143,145,146,148,150,151,153,155,
+156,158,160,162,163,165,167,169,171,172,174,176,
+178,180,182,183,185,187,189,191,193,195,197,199,
+201,203,205,207,209,211,213,215,217,219,221,223,
+225,227,229,231,233,235,237,240,242,244,246,248,
+250,253,255,257,259,261,264,266,268,270,273,275,
+277,280,282,284,287,289,291,294,296,298,301,303,
+306,308,310,313,315,318,320,323,325,328,330,333,
+335,338,340,343,345,348,351,353,356,358,361,364,
+366,369,372,374,377,380,382,385,388,390,393,396,
+399,401,404,407,410,412,415,418,421,424,427,429,
+432,435,438,441,444,447,450,453,456,458,461,464,
+467,470,473,476,479,482,485,488,492,495,498,501,
+504,507,510,513,516,519,523,526,529,532,535,538,
+542,545,548,551,554,558,561,564,567,571,574,577,
+581,584,587,591,594,597,601,604,607,611,614,618,
+621,625,628,631,635,638,642,645,649,652,656,659,
+663,666,670,674,677,681,684,688,691,695,699,702,
+706,710,713,717,721,724,728,732,735,739,743,747,
+750,754,758,762,766,769,773,777,781,785,788,792,
+796,800,804,808,812,816,820,823,827,831,835,839,
+843,847,851,855,859,863,867,871,875,879,884,888,
+892,896,900,904,908,912,916,921,925,929,933,937,
+941,946,950,954,958,962,967,971,975,980,984,988,
+992,997,1001,1005,1010,1014,1018,1023,1027,1032,1036,1040,
+1045,1049,1054,1058,1062,1067,1071,1076,1080,1085,1089,1094,
+1098,1103,1107,1112,1117,1121,1126,1130,1135,1139,1144,1149,
+1153,1158,1163,1167,1172,1177,1181,1186,1191,1195,1200,1205,
+1209,1214,1219,1224,1228,1233,1238,1243,1248,1252,1257,1262,
+1267,1272,1277,1282,1286,1291,1296,1301,1306,1311,1316,1321,
+1326,1331,1336,1341,1346,1351,1356,1361,1366,1371,1376,1381,
+1386,1391,1396,1401,1406,1411,1416,1421,1427,1432,1437,1442,
+1447,1452,1457,1463,1468,1473,1478,1483,1489,1494,1499,1504,
+1510,1515,1520,1526,1531,1536,1541,1547,1552,1557,1563,1568,
+1574,1579,1584,1590,1595,1601,1606,1611,1617,1622,1628,1633,
+1639,1644,1650,1655,1661,1666,1672,1677,1683,1688,1694,1699,
+1705,1711,1716,1722,1727,1733,1739,1744,1750,1756,1761,1767,
+1773,1778,1784,1790,1795,1801,1807,1813,1818,1824,1830,1836,
+1841,1847,1853,1859,1865,1870,1876,1882,1888,1894,1900,1906,
+1911,1917,1923,1929,1935,1941,1947,1953,1959,1965,1971,1977,
+1983,1989,1995,2001,2007,2013,2019,2025,2031,2037,2043,2049,
+2055,2061,2067,2074,2080,2086,2092,2098,2104,2110,2117,2123,
+2129,2135,2141,2148,2154,2160,2166,2173,2179,2185,2191,2198,
+2204,2210,2217,2223,2229,2236,2242,2248,2255,2261,2267,2274,
+2280,2286,2293,2299,2306,2312,2319,2325,2331,2338,2344,2351,
+2357,2364,2370,2377,2383,2390,2396,2403,2410,2416,2423,2429,
+2436,2442,2449,2456,2462,2469,2476,2482,2489,2496,2502,2509,
+2516,2522,2529,2536,2542,2549,2556,2563,2569,2576,2583,2590,
+2596,2603,2610,2617,2624,2631,2637,2644,2651,2658,2665,2672,
+2679,2685,2692,2699,2706,2713,2720,2727,2734,2741,2748,2755,
+2762,2769,2776,2783,2790,2797,2804,2811,2818,2825,2832,2839,
+2846,2853,2860,2867,2874,2882,2889,2896,2903,2910,2917,2924,
+2932,2939,2946,2953,2960,2968,2975,2982,2989,2996,3004,3011,
+3018,3025,3033,3040,3047,3055,3062,3069,3077,3084,3091,3099,
+3106,3113,3121,3128,3135,3143,3150,3158,3165,3173,3180,3187,
+3195,3202,3210,3217,3225,3232,3240,3247,3255,3262,3270,3277,
+3285,3292,3300,3308,3315,3323,3330,3338,3346,3353,3361,3368,
+3376,3384,3391,3399,3407,3414,3422,3430,3437,3445,3453,3461,
+3468,3476,3484,3491,3499,3507,3515,3523,3530,3538,3546,3554,
+3562,3569,3577,3585,3593,3601,3609,3616,3624,3632,3640,3648,
+3656,3664,3672,3680,3688,3696,3704,3712,3719,3727,3735,3743,
+3751,3759,3767,3775,3784,3792,3800,3808,3816,3824,3832,3840,
+3848,3856,3864,3872,3880,3889,3897,3905,3913,3921,3929,3937,
+3946,3954,3962,3970,3978,3987,3995,4003,4011,4020,4028,4036,
+4044,4053,4061,4069,4077,4086,4094,4102,4111,4119,4127,4136,
+4144,4152,4161,4169,4177,4186,4194,4203,4211,4219,4228,4236,
+4245,4253,4262,4270,4279,4287,4296,4304,4312,4321,4330,4338,
+4347,4355,4364,4372,4381,4389,4398,4406,4415,4424,4432,4441,
+4449,4458,4467,4475,4484,4492,4501,4510,4518,4527,4536,4544,
+4553,4562,4571,4579,4588,4597,4605,4614,4623,4632,4640,4649,
+4658,4667,4676,4684,4693,4702,4711,4720,4728,4737,4746,4755,
+4764,4773,4782,4790,4800,4809,4818,4827,4836,4845,4854,4863,
+4872,4881,4890,4899,4908,4916,4925,4934,4943,4952,4961,4970,
+4979,4988,4998,5007,5016,5025,5034,5043,5052,5061,5070,5079,
+5088,5097,5106,5116,5125,5134,5143,5152,5161,5170,5180,5189,
+5198,5207,5216,5225,5235,5244,5253,5262,5272,5281,5290,5299,
+5309,5318,5327,5336,5346,5355,5364,5374,5383,5392,5401,5411,
+5420,5429,5439,5448,5458,5467,5476,5486,5495,5504,5514,5523,
+5533,5542,5551,5561,5570,5580,5589,5599,5608,5618,5627,5637,
+5646,5656,5665,5675,5684,5694,5703,5713,5722,5732,5741,5751,
+5760,5770,5780,5789,5799,5808,5818,5828,5837,5847,5856,5866,
+5876,5885,5895,5905,5914,5924,5934,5943,5953,5963,5972,5982,
+5992,6002,6011,6021,6031,6040,6050,6060,6070,6079,6089,6099,
+6109,6119,6128,6138,6148,6158,6168,6177,6187,6197,6207,6217,
+6227,6237,6246,6256,6266,6276,6286,6296,6306,6316,6326,6336,
+6345,6355,6365,6375,6385,6395,6405,6415,6425,6435,6445,6455,
+6465,6475,6485,6495,6505,6515,6525,6535,6545,6555,6565,6575,
+6585,6596,6606,6616,6626,6636,6646,6656,6666,6676,6686,6697,
+6707,6717,6727,6737,6747,6758,6768,6778,6788,6798,6808,6819,
+6829,6839,6849,6859,6870,6880,6890,6900,6911,6921,6931,6941,
+6952,6962,6972,6983,6993,7003,7013,7024,7034,7044,7055,7065,
+7075,7086,7096,7106,7117,7127,7138,7148,7158,7169,7179,7190,
+7200,7210,7221,7231,7242,7252,7262,7273,7283,7294,7304,7315,
+7325,7336,7346,7357,7367,7378,7388,7399,7409,7420,7430,7441,
+7451,7462,7472,7483,7493,7504,7515,7525,7536,7546,7557,7567,
+7578,7589,7599,7610,7620,7631,7642,7652,7663,7674,7684,7695,
+7706,7716,7727,7738,7748,7759,7770,7780,7791,7802,7812,7823,
+7834,7845,7855,7866,7877,7887,7898,7909,7920,7930,7941,7952,
+7963,7974,7984,7995,8006,8017,8028,8038,8049,8060,8071,8082,
+8092,8103,8114,8125,8136,8147,8158,8168,8179,8190,8201,8212,
+8223,8234,8245,8256,8267,8277,8288,8299,8310,8321,8332,8343,
+8354,8365,8376,8387,8398,8409,8420,8431,8442,8453,8464,8475,
+8486,8497,8508,8519,8530,8541,8552,8563,8574,8585,8596,8607,
+8618,8629,8640,8651,8663,8674,8685,8696,8707,8718,8729,8740,
+8751,8762,8774,8785,8796,8807,8818,8829,8840,8852,8863,8874,
+8885,8896,8907,8919,8930,8941,8952,8963,8975,8986,8997,9008,
+9019,9031,9042,9053,9064,9076,9087,9098,9109,9121,9132,9143,
+9154,9166,9177,9188,9200,9211,9222,9234,9245,9256,9267,9279,
+9290,9301,9313,9324,9335,9347,9358,9369,9381,9392,9404,9415,
+9426,9438,9449,9460,9472,9483,9495,9506,9517,9529,9540,9552,
+9563,9575,9586,9597,9609,9620,9632,9643,9655,9666,9678,9689,
+9701,9712,9723,9735,9746,9758,9769,9781,9792,9804,9815,9827,
+9838,9850,9862,9873,9885,9896,9908,9919,9931,9942,9954,9965,
+9977,9989,10000,10012,10023,10035,10046,10058,10070,10081,10093,10104,
+10116,10128,10139,10151,10163,10174,10186,10197,10209,10221,10232,10244,
+10256,10267,10279,10291,10302,10314,10326,10337,10349,10361,10372,10384,
+10396,10407,10419,10431,10443,10454,10466,10478,10489,10501,10513,10525,
+10536,10548,10560,10572,10583,10595,10607,10619,10630,10642,10654,10666,
+10677,10689,10701,10713,10725,10736,10748,10760,10772,10784,10795,10807,
+10819,10831,10843,10855,10866,10878,10890,10902,10914,10926,10937,10949,
+10961,10973,10985,10997,11009,11020,11032,11044,11056,11068,11080,11092,
+11104,11116,11127,11139,11151,11163,11175,11187,11199,11211,11223,11235,
+11247,11259,11271,11282,11294,11306,11318,11330,11342,11354,11366,11378,
+11390,11402,11414,11426,11438,11450,11462,11474,11486,11498,11510,11522,
+11534,11546,11558,11570,11582,11594,11606,11618,11630,11642,11654,11666,
+11678,11690,11702,11714,11726,11738,11750,11762,11774,11787,11799,11811,
+11823,11835,11847,11859,11871,11883,11895,11907,11919,11931,11944,11956,
+11968,11980,11992,12004,12016,12028,12040,12053,12065,12077,12089,12101,
+12113,12125,12137,12150,12162,12174,12186,12198,12210,12222,12235,12247,
+12259,12271,12283,12295,12308,12320,12332,12344,12356,12368,12381,12393,
+12405,12417,12429,12442,12454,12466,12478,12490,12503,12515,12527,12539,
+12551,12564,12576,12588,12600,12613,12625,12637,12649,12662,12674,12686,
+12698,12711,12723,12735,12747,12760,12772,12784,12796,12809,12821,12833,
+12845,12858,12870,12882,12894,12907,12919,12931,12944,12956,12968,12980,
+12993,13005,13017,13030,13042,13054,13067,13079,13091,13103,13116,13128,
+13140,13153,13165,13177,13190,13202,13214,13227,13239,13251,13264,13276,
+13288,13301,13313,13325,13338,13350,13362,13375,13387,13399,13412,13424,
+13437,13449,13461,13474,13486,13498,13511,13523,13535,13548,13560,13573,
+13585,13597,13610,13622,13635,13647,13659,13672,13684,13697,13709,13721,
+13734,13746,13759,13771,13783,13796,13808,13821,13833,13845,13858,13870,
+13883,13895,13907,13920,13932,13945,13957,13970,13982,13994,14007,14019,
+14032,14044,14057,14069,14082,14094,14106,14119,14131,14144,14156,14169,
+14181,14194,14206,14218,14231,14243,14256,14268,14281,14293,14306,14318,
+14331,14343,14356,14368,14380,14393,14405,14418,14430,14443,14455,14468,
+14480,14493,14505,14518,14530,14543,14555,14568,14580,14593,14605,14618,
+14630,14643,14655,14668,14680,14693,14705,14718,14730,14743,14755,14768,
+14780,14793,14805,14818,14830,14843,14855,14868,14880,14893,14905,14918,
+14930,14943,14955,14968,14980,14993,15005,15018,15030,15043,15055,15068,
+15081,15093,15106,15118,15131,15143,15156,15168,15181,15193,15206,15218,
+15231,15243,15256,15269,15281,15294,15306,15319,15331,15344,15356,15369,
+15381,15394,15406,15419,15432,15444,15457,15469,15482,15494,15507,15519,
+15532,15544,15557,15570,15582,15595,15607,15620,15632,15645,15657,15670,
+15683,15695,15708,15720,15733,15745,15758,15770,15783,15796,15808,15821,
+15833,15846,15858,15871,15883,15896,15909,15921,15934,15946,15959,15971,
+15984,15997,16009,16022,16034,16047,16059,16072,16084,16097,16110,16122,
+16135,16147,16160,16172,16185,16198,16210,16223,16235,16248,16260,16273,
+16286,16298,16311,16323,16336,16348,16361,16374,16388,16400,16413,16425,
+16438,16450,16463,16476,16488,16501,16513,16526,16538,16551,16564,16576,
+16589,16601,16614,16626,16639,16652,16664,16677,16689,16702,16714,16727,
+16739,16752,16765,16777,16790,16802,16815,16827,16840,16853,16865,16878,
+16890,16903,16915,16928,16940,16953,16966,16978,16991,17003,17016,17028,
+17041,17053,17066,17079,17091,17104,17116,17129,17141,17154,17166,17179,
+17192,17204,17217,17229,17242,17254,17267,17279,17292,17305,17317,17330,
+17342,17355,17367,17380,17392,17405,17417,17430,17442,17455,17468,17480,
+17493,17505,17518,17530,17543,17555,17568,17580,17593,17605,17618,17631,
+17643,17656,17668,17681,17693,17706,17718,17731,17743,17756,17768,17781,
+17793,17806,17818,17831,17843,17856,17868,17881,17893,17906,17918,17931,
+17944,17956,17969,17981,17994,18006,18019,18031,18044,18056,18069,18081,
+18094,18106,18119,18131,18144,18156,18169,18181,18194,18206,18218,18231,
+18243,18256,18268,18281,18293,18306,18318,18331,18343,18356,18368,18381,
+18393,18406,18418,18431,18443,18456,18468,18480,18493,18505,18518,18530,
+18543,18555,18568,18580,18593,18605,18617,18630,18642,18655,18667,18680,
+18692,18705,18717,18729,18742,18754,18767,18779,18792,18804,18816,18829,
+18841,18854,18866,18879,18891,18903,18916,18928,18941,18953,18966,18978,
+18990,19003,19015,19028,19040,19052,19065,19077,19090,19102,19114,19127,
+19139,19151,19164,19176,19189,19201,19213,19226,19238,19251,19263,19275,
+19288,19300,19312,19325,19337,19349,19362,19374,19387,19399,19411,19424,
+19436,19448,19461,19473,19485,19498,19510,19522,19535,19547,19559,19572,
+19584,19596,19609,19621,19633,19646,19658,19670,19682,19695,19707,19719,
+19732,19744,19756,19769,19781,19793,19805,19818,19830,19842,19855,19867,
+19879,19891,19904,19916,19928,19941,19953,19965,19977,19990,20002,20014,
+20026,20039,20051,20063,20075,20088,20100,20112,20124,20137,20149,20161,
+20173,20185,20198,20210,20222,20234,20247,20259,20271,20283,20295,20308,
+20320,20332,20344,20356,20369,20381,20393,20405,20417,20429,20442,20454,
+20466,20478,20490,20502,20515,20527,20539,20551,20563,20575,20588,20600,
+20612,20624,20636,20648,20660,20673,20685,20697,20709,20721,20733,20745,
+20757,20769,20782,20794,20806,20818,20830,20842,20854,20866,20878,20890,
+20902,20915,20927,20939,20951,20963,20975,20987,20999,21011,21023,21035,
+21047,21059,21071,21083,21095,21107,21119,21132,21144,21156,21168,21180,
+21192,21204,21216,21228,21240,21252,21264,21276,21288,21300,21312,21324,
+21336,21348,21360,21371,21383,21395,21407,21419,21431,21443,21455,21467,
+21479,21491,21503,21515,21527,21539,21551,21563,21575,21586,21598,21610,
+21622,21634,21646,21658,21670,21682,21694,21705,21717,21729,21741,21753,
+21765,21777,21789,21800,21812,21824,21836,21848,21860,21872,21883,21895,
+21907,21919,21931,21943,21954,21966,21978,21990,22002,22013,22025,22037,
+22049,22061,22072,22084,22096,22108,22119,22131,22143,22155,22167,22178,
+22190,22202,22214,22225,22237,22249,22260,22272,22284,22296,22307,22319,
+22331,22343,22354,22366,22378,22389,22401,22413,22424,22436,22448,22459,
+22471,22483,22494,22506,22518,22529,22541,22553,22564,22576,22588,22599,
+22611,22622,22634,22646,22657,22669,22680,22692,22704,22715,22727,22738,
+22750,22762,22773,22785,22796,22808,22819,22831,22843,22854,22866,22877,
+22889,22900,22912,22923,22935,22946,22958,22969,22981,22992,23004,23015,
+23027,23038,23050,23061,23073,23084,23096,23107,23119,23130,23142,23153,
+23164,23176,23187,23199,23210,23222,23233,23244,23256,23267,23279,23290,
+23301,23313,23324,23336,23347,23358,23370,23381,23392,23404,23415,23426,
+23438,23449,23460,23472,23483,23494,23506,23517,23528,23540,23551,23562,
+23574,23585,23596,23607,23619,23630,23641,23653,23664,23675,23686,23698,
+23709,23720,23731,23743,23754,23765,23776,23787,23799,23810,23821,23832,
+23843,23855,23866,23877,23888,23899,23910,23922,23933,23944,23955,23966,
+23977,23988,24000,24011,24022,24033,24044,24055,24066,24077,24088,24100,
+24111,24122,24133,24144,24155,24166,24177,24188,24199,24210,24221,24232,
+24243,24254,24265,24276,24287,24298,24309,24320,24331,24342,24353,24364,
+24375,24386,24397,24408,24419,24430,24441,24452,24463,24474,24485,24496,
+24507,24517,24528,24539,24550,24561,24572,24583,24594,24605,24615,24626,
+24637,24648,24659,24670,24681,24691,24702,24713,24724,24735,24746,24756,
+24767,24778,24789,24799,24810,24821,24832,24843,24853,24864,24875,24886,
+24896,24907,24918,24929,24939,24950,24961,24971,24982,24993,25003,25014,
+25025,25035,25046,25057,25067,25078,25089,25099,25110,25121,25131,25142,
+25153,25163,25174,25184,25195,25206,25216,25227,25237,25248,25258,25269,
+25280,25290,25301,25311,25322,25332,25343,25353,25364,25374,25385,25395,
+25406,25416,25427,25437,25448,25458,25469,25479,25490,25500,25510,25521,
+25531,25542,25552,25563,25573,25583,25594,25604,25615,25625,25635,25646,
+25656,25666,25677,25687,25697,25708,25718,25728,25739,25749,25759,25770,
+25780,25790,25801,25811,25821,25831,25842,25852,25862,25872,25883,25893,
+25903,25913,25924,25934,25944,25954,25964,25975,25985,25995,26005,26015,
+26025,26036,26046,26056,26066,26076,26086,26096,26107,26117,26127,26137,
+26147,26157,26167,26177,26187,26197,26207,26217,26228,26238,26248,26258,
+26268,26278,26288,26298,26308,26318,26328,26338,26348,26358,26368,26378,
+26388,26397,26407,26417,26427,26437,26447,26457,26467,26477,26487,26497,
+26507,26516,26526,26536,26546,26556,26566,26576,26585,26595,26605,26615,
+26625,26634,26644,26654,26664,26674,26683,26693,26703,26713,26722,26732,
+26742,26752,26761,26771,26781,26791,26800,26810,26820,26829,26839,26849,
+26858,26868,26878,26887,26897,26907,26916,26926,26935,26945,26955,26964,
+26974,26983,26993,27003,27012,27022,27031,27041,27050,27060,27069,27079,
+27088,27098,27107,27117,27126,27136,27145,27155,27164,27174,27183,27193,
+27202,27212,27221,27230,27240,27249,27259,27268,27277,27287,27296,27306,
+27315,27324,27334,27343,27352,27362,27371,27380,27390,27399,27408,27418,
+27427,27436,27445,27455,27464,27473,27482,27492,27501,27510,27519,27529,
+27538,27547,27556,27565,27575,27584,27593,27602,27611,27620,27629,27639,
+27648,27657,27666,27675,27684,27693,27702,27711,27721,27730,27739,27748,
+27757,27766,27775,27784,27793,27802,27811,27820,27829,27838,27847,27856,
+27865,27874,27883,27892,27901,27910,27919,27927,27936,27945,27954,27963,
+27973,27982,27991,28000,28009,28017,28026,28035,28044,28053,28062,28070,
+28079,28088,28097,28106,28114,28123,28132,28141,28149,28158,28167,28176,
+28184,28193,28202,28210,28219,28228,28236,28245,28254,28262,28271,28280,
+28288,28297,28306,28314,28323,28331,28340,28349,28357,28366,28374,28383,
+28392,28400,28409,28417,28426,28434,28443,28451,28460,28468,28477,28485,
+28494,28502,28511,28519,28527,28536,28544,28553,28561,28569,28578,28586,
+28595,28603,28611,28620,28628,28636,28645,28653,28661,28670,28678,28686,
+28695,28703,28711,28720,28728,28736,28744,28753,28761,28769,28777,28785,
+28794,28802,28810,28818,28826,28835,28843,28851,28859,28867,28875,28884,
+28892,28900,28908,28916,28924,28932,28940,28948,28956,28964,28972,28980,
+28989,28997,29005,29013,29021,29029,29037,29045,29052,29060,29068,29076,
+29084,29092,29100,29108,29116,29124,29132,29140,29148,29155,29163,29171,
+29179,29187,29195,29203,29210,29218,29226,29234,29242,29249,29257,29265,
+29273,29280,29288,29296,29304,29311,29319,29327,29335,29342,29350,29358,
+29365,29373,29381,29388,29396,29403,29411,29419,29426,29434,29442,29449,
+29457,29464,29472,29479,29487,29494,29502,29510,29517,29525,29532,29540,
+29547,29555,29562,29569,29577,29584,29592,29599,29607,29614,29621,29629,
+29636,29644,29651,29658,29666,29673,29680,29688,29695,29702,29710,29717,
+29724,29732,29739,29746,29754,29761,29768,29775,29783,29790,29797,29804,
+29811,29819,29826,29833,29840,29847,29854,29862,29869,29876,29883,29890,
+29897,29904,29911,29919,29926,29933,29940,29947,29954,29961,29968,29975,
+29982,29989,29996,30003,30010,30017,30024,30031,30038,30045,30052,30059,
+30065,30072,30079,30086,30093,30100,30107,30114,30121,30127,30134,30141,
+30148,30155,30161,30168,30175,30182,30189,30195,30202,30209,30216,30222,
+30229,30236,30243,30249,30256,30263,30269,30276,30283,30289,30296,30303,
+30309,30316,30322,30329,30336,30342,30349,30355,30362,30368,30375,30381,
+30388,30395,30401,30408,30414,30421,30427,30433,30440,30446,30453,30459,
+30466,30472,30479,30485,30491,30498,30504,30510,30517,30523,30530,30536,
+30542,30549,30555,30561,30567,30574,30580,30586,30593,30599,30605,30611,
+30617,30624,30630,30636,30642,30649,30655,30661,30667,30673,30679,30685,
+30692,30698,30704,30710,30716,30722,30728,30734,30740,30746,30752,30758,
+30764,30770,30776,30782,30788,30794,30800,30806,30812,30818,30824,30830,
+30836,30842,30848,30854,30860,30866,30871,30877,30883,30889,30895,30901,
+30907,30912,30918,30924,30930,30936,30941,30947,30953,30959,30964,30970,
+30976,30981,30987,30993,30999,31004,31010,31016,31021,31027,31032,31038,
+31044,31049,31055,31061,31066,31072,31077,31083,31088,31094,31099,31105,
+31110,31116,31121,31127,31132,31138,31143,31149,31154,31160,31165,31171,
+31176,31181,31187,31192,31197,31203,31208,31214,31219,31224,31230,31235,
+31240,31245,31251,31256,31261,31267,31272,31277,31282,31287,31293,31298,
+31303,31308,31313,31319,31324,31329,31334,31339,31344,31350,31355,31360,
+31365,31370,31375,31380,31385,31390,31395,31400,31405,31410,31415,31420,
+31425,31430,31435,31440,31445,31450,31455,31460,31465,31470,31475,31480,
+31484,31489,31494,31499,31504,31509,31514,31518,31523,31528,31533,31538,
+31542,31547,31552,31557,31561,31566,31571,31575,31580,31585,31590,31594,
+31599,31604,31608,31613,31617,31622,31627,31631,31636,31640,31645,31650,
+31654,31659,31663,31668,31672,31677,31681,31686,31690,31695,31699,31704,
+31708,31713,31717,31722,31726,31730,31735,31739,31744,31748,31752,31757,
+31761,31765,31770,31774,31778,31783,31787,31791,31795,31800,31804,31808,
+31812,31817,31821,31825,31829,31833,31838,31842,31846,31850,31854,31858,
+31862,31867,31871,31875,31879,31883,31887,31891,31895,31899,31903,31907,
+31911,31915,31919,31923,31927,31931,31935,31939,31943,31947,31951,31955,
+31959,31963,31967,31970,31974,31978,31982,31986,31990,31993,31997,32001,
+32005,32009,32012,32016,32020,32024,32027,32031,32035,32039,32042,32046,
+32050,32053,32057,32061,32064,32068,32072,32075,32079,32082,32086,32090,
+32093,32097,32100,32104,32107,32111,32114,32118,32122,32125,32128,32132,
+32135,32139,32142,32146,32149,32153,32156,32159,32163,32166,32170,32173,
+32176,32180,32183,32186,32190,32193,32196,32199,32203,32206,32209,32213,
+32216,32219,32222,32225,32229,32232,32235,32238,32241,32245,32248,32251,
+32254,32257,32260,32263,32266,32269,32273,32276,32279,32282,32285,32288,
+32291,32294,32297,32300,32303,32306,32309,32312,32315,32317,32320,32323,
+32326,32329,32332,32335,32338,32341,32343,32346,32349,32352,32355,32358,
+32360,32363,32366,32369,32371,32374,32377,32380,32382,32385,32388,32390,
+32393,32396,32398,32401,32404,32406,32409,32412,32414,32417,32419,32422,
+32425,32427,32430,32432,32435,32437,32440,32442,32445,32447,32450,32452,
+32455,32457,32459,32462,32464,32467,32469,32472,32474,32476,32479,32481,
+32483,32486,32488,32490,32493,32495,32497,32499,32502,32504,32506,32508,
+32511,32513,32515,32517,32519,32522,32524,32526,32528,32530,32532,32534,
+32537,32539,32541,32543,32545,32547,32549,32551,32553,32555,32557,32559,
+32561,32563,32565,32567,32569,32571,32573,32575,32577,32579,32581,32583,
+32584,32586,32588,32590,32592,32594,32596,32597,32599,32601,32603,32605,
+32606,32608,32610,32612,32613,32615,32617,32618,32620,32622,32623,32625,
+32627,32628,32630,32632,32633,32635,32636,32638,32640,32641,32643,32644,
+32646,32647,32649,32650,32652,32653,32655,32656,32658,32659,32661,32662,
+32664,32665,32666,32668,32669,32671,32672,32673,32675,32676,32677,32679,
+32680,32681,32683,32684,32685,32686,32688,32689,32690,32691,32693,32694,
+32695,32696,32697,32698,32700,32701,32702,32703,32704,32705,32706,32707,
+32708,32710,32711,32712,32713,32714,32715,32716,32717,32718,32719,32720,
+32721,32722,32723,32724,32724,32725,32726,32727,32728,32729,32730,32731,
+32732,32732,32733,32734,32735,32736,32736,32737,32738,32739,32739,32740,
+32741,32742,32742,32743,32744,32744,32745,32746,32746,32747,32748,32748,
+32749,32750,32750,32751,32751,32752,32752,32753,32754,32754,32755,32755,
+32756,32756,32757,32757,32758,32758,32758,32759,32759,32760,32760,32761,
+32761,32761,32762,32762,32762,32763,32763,32763,32764,32764,32764,32765,
+32765,32765,32765,32766,32766,32766,32766,32766,32767,32767,32767,32767,
+32767,32767,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,
+32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,
+32768,32768,32768,32768,32768,32768,32767,32767,32767,32767,32767,32767,
+32766,32766,32766,32766,32766,32765,32765,32765,32765,32764,32764,32764,
+32763,32763,32763,32762,32762,32762,32761,32761,32761,32760,32760,32759,
+32759,32759,32758,32758,32757,32757,32756,32756,32755,32755,32754,32754,
+32753,32753,32752,32751,32751,32750,32750,32749,32748,32748,32747,32747,
+32746,32745,32745,32744,32743,32742,32742,32741,32740,32740,32739,32738,
+32737,32737,32736,32735,32734,32733,32732,32732,32731,32730,32729,32728,
+32727,32726,32725,32725,32724,32723,32722,32721,32720,32719,32718,32717,
+32716,32715,32714,32713,32712,32711,32710,32709,32708,32706,32705,32704,
+32703,32702,32701,32700,32699,32697,32696,32695,32694,32693,32691,32690,
+32689,32688,32686,32685,32684,32683,32681,32680,32679,32677,32676,32675,
+32673,32672,32671,32669,32668,32667,32665,32664,32662,32661,32659,32658,
+32657,32655,32654,32652,32651,32649,32648,32646,32645,32643,32641,32640,
+32638,32637,32635,32633,32632,32630,32629,32627,32625,32624,32622,32620,
+32619,32617,32615,32613,32612,32610,32608,32606,32605,32603,32601,32599,
+32598,32596,32594,32592,32590,32588,32587,32585,32583,32581,32579,32577,
+32575,32573,32571,32569,32567,32565,32563,32561,32559,32557,32555,32553,
+32551,32549,32547,32545,32543,32541,32539,32537,32535,32533,32531,32528,
+32526,32524,32522,32520,32518,32515,32513,32511,32509,32506,32504,32502,
+32500,32497,32495,32493,32491,32488,32486,32484,32481,32479,32477,32474,
+32472,32469,32467,32465,32462,32460,32457,32455,32452,32450,32448,32445,
+32443,32440,32438,32435,32433,32430,32427,32425,32422,32420,32417,32415,
+32412,32409,32407,32404,32401,32399,32396,32393,32391,32388,32385,32383,
+32380,32377,32375,32372,32369,32366,32363,32361,32358,32355,32352,32349,
+32347,32344,32341,32338,32335,32332,32329,32327,32324,32321,32318,32315,
+32312,32309,32306,32303,32300,32297,32294,32291,32288,32285,32282,32279,
+32276,32273,32270,32267,32264,32261,32257,32254,32251,32248,32245,32242,
+32239,32235,32232,32229,32226,32223,32219,32216,32213,32210,32206,32203,
+32200,32197,32193,32190,32187,32183,32180,32177,32173,32170,32167,32163,
+32160,32156,32153,32150,32146,32143,32139,32136,32132,32129,32125,32122,
+32118,32115,32111,32108,32104,32101,32097,32094,32090,32087,32083,32079,
+32076,32072,32068,32065,32061,32058,32054,32050,32047,32043,32039,32035,
+32032,32028,32024,32020,32017,32013,32009,32005,32002,31998,31994,31990,
+31986,31982,31979,31975,31971,31967,31963,31959,31955,31951,31947,31944,
+31940,31936,31932,31928,31924,31920,31916,31912,31908,31904,31900,31896,
+31892,31888,31883,31879,31875,31871,31867,31863,31859,31855,31851,31846,
+31842,31838,31834,31830,31826,31821,31817,31813,31809,31804,31800,31796,
+31792,31787,31783,31779,31774,31770,31766,31761,31757,31753,31748,31744,
+31740,31735,31731,31726,31722,31718,31713,31709,31704,31700,31695,31691,
+31686,31682,31677,31673,31668,31664,31659,31655,31650,31646,31641,31636,
+31632,31627,31623,31618,31613,31609,31604,31599,31595,31590,31585,31581,
+31576,31571,31567,31562,31557,31552,31548,31543,31538,31533,31529,31524,
+31519,31514,31509,31504,31500,31495,31490,31485,31480,31475,31470,31465,
+31461,31456,31451,31446,31441,31436,31431,31426,31421,31416,31411,31406,
+31401,31396,31391,31386,31381,31376,31371,31365,31360,31355,31350,31345,
+31340,31335,31330,31324,31319,31314,31309,31304,31299,31293,31288,31283,
+31278,31272,31267,31262,31257,31251,31246,31241,31236,31230,31225,31220,
+31214,31209,31204,31198,31193,31187,31182,31177,31171,31166,31160,31155,
+31149,31144,31139,31133,31128,31122,31117,31111,31106,31100,31095,31089,
+31083,31078,31072,31067,31061,31056,31050,31044,31039,31033,31028,31022,
+31016,31011,31005,30999,30994,30988,30982,30976,30971,30965,30959,30954,
+30948,30942,30936,30930,30925,30919,30913,30907,30901,30896,30890,30884,
+30878,30872,30866,30860,30855,30849,30843,30837,30831,30825,30819,30813,
+30807,30801,30795,30789,30783,30777,30771,30765,30759,30753,30747,30741,
+30735,30729,30723,30717,30711,30705,30698,30692,30686,30680,30674,30668,
+30662,30655,30649,30643,30637,30631,30624,30618,30612,30606,30600,30593,
+30587,30581,30575,30568,30562,30556,30549,30543,30537,30530,30524,30518,
+30511,30505,30499,30492,30486,30479,30473,30467,30460,30454,30447,30441,
+30434,30428,30421,30415,30408,30402,30395,30389,30382,30376,30369,30363,
+30356,30350,30343,30336,30330,30323,30317,30310,30303,30297,30290,30283,
+30277,30270,30263,30257,30250,30243,30237,30230,30223,30216,30210,30203,
+30196,30189,30183,30176,30169,30162,30156,30149,30142,30135,30128,30121,
+30115,30108,30101,30094,30087,30080,30073,30066,30059,30053,30046,30039,
+30032,30025,30018,30011,30004,29997,29990,29983,29976,29969,29962,29955,
+29948,29941,29934,29926,29919,29912,29905,29898,29891,29884,29877,29870,
+29862,29855,29848,29841,29834,29827,29819,29812,29805,29798,29791,29783,
+29776,29769,29762,29754,29747,29740,29733,29725,29718,29711,29703,29696,
+29689,29681,29674,29667,29659,29652,29645,29637,29630,29622,29615,29608,
+29600,29593,29585,29578,29570,29563,29555,29548,29541,29533,29526,29518,
+29510,29503,29495,29488,29480,29473,29465,29458,29450,29442,29435,29427,
+29420,29412,29404,29397,29389,29382,29374,29366,29359,29351,29343,29335,
+29328,29320,29312,29305,29297,29289,29281,29274,29266,29258,29250,29243,
+29235,29227,29219,29211,29204,29196,29188,29180,29172,29164,29156,29149,
+29141,29133,29125,29117,29109,29101,29093,29085,29077,29069,29061,29053,
+29046,29038,29030,29022,29014,29006,28998,28990,28981,28973,28965,28957,
+28949,28941,28933,28925,28917,28909,28901,28893,28885,28876,28868,28860,
+28852,28844,28836,28827,28819,28811,28803,28795,28787,28778,28770,28762,
+28754,28745,28737,28729,28721,28712,28704,28696,28687,28679,28671,28663,
+28654,28646,28638,28629,28621,28612,28604,28596,28587,28579,28571,28562,
+28554,28545,28537,28528,28520,28512,28503,28495,28486,28478,28469,28461,
+28452,28444,28435,28427,28418,28410,28401,28393,28384,28375,28367,28358,
+28350,28341,28333,28324,28315,28307,28298,28289,28281,28272,28264,28255,
+28246,28238,28229,28220,28212,28203,28194,28185,28177,28168,28159,28150,
+28142,28133,28124,28115,28107,28098,28089,28080,28071,28063,28054,28045,
+28036,28027,28019,28010,28001,27992,27983,27974,27964,27955,27946,27937,
+27929,27920,27911,27902,27893,27884,27875,27866,27857,27848,27839,27830,
+27821,27812,27803,27794,27785,27776,27767,27758,27749,27740,27731,27722,
+27713,27704,27694,27685,27676,27667,27658,27649,27640,27631,27621,27612,
+27603,27594,27585,27576,27567,27557,27548,27539,27530,27520,27511,27502,
+27493,27484,27474,27465,27456,27447,27437,27428,27419,27409,27400,27391,
+27382,27372,27363,27354,27344,27335,27325,27316,27307,27297,27288,27279,
+27269,27260,27250,27241,27232,27222,27213,27203,27194,27184,27175,27166,
+27156,27147,27137,27128,27118,27109,27099,27090,27080,27071,27061,27052,
+27042,27032,27023,27013,27004,26994,26985,26975,26965,26956,26946,26937,
+26927,26917,26908,26898,26888,26879,26869,26860,26850,26840,26831,26821,
+26811,26801,26792,26782,26772,26763,26753,26743,26733,26724,26714,26704,
+26694,26685,26675,26665,26655,26645,26636,26626,26616,26606,26596,26587,
+26577,26567,26557,26547,26537,26527,26518,26508,26498,26488,26478,26468,
+26458,26448,26438,26429,26419,26409,26399,26389,26379,26369,26359,26349,
+26339,26329,26319,26309,26299,26289,26279,26269,26259,26249,26239,26229,
+26219,26209,26199,26189,26178,26168,26158,26148,26138,26128,26118,26108,
+26098,26088,26077,26067,26057,26047,26037,26027,26017,26006,25996,25986,
+25976,25966,25955,25945,25935,25925,25915,25904,25894,25884,25874,25863,
+25853,25843,25833,25822,25812,25802,25792,25781,25771,25761,25750,25740,
+25730,25719,25709,25699,25688,25678,25668,25657,25647,25637,25626,25616,
+25605,25595,25585,25574,25564,25553,25543,25533,25522,25512,25501,25491,
+25480,25470,25460,25449,25439,25428,25418,25407,25397,25386,25376,25365,
+25355,25344,25334,25323,25313,25302,25291,25281,25270,25260,25249,25239,
+25228,25217,25207,25196,25186,25175,25164,25154,25143,25133,25122,25111,
+25101,25090,25079,25069,25058,25047,25037,25026,25015,25005,24994,24983,
+24973,24962,24951,24941,24930,24919,24908,24898,24887,24876,24865,24855,
+24844,24833,24822,24812,24801,24790,24779,24768,24758,24747,24736,24725,
+24714,24704,24693,24682,24671,24660,24649,24639,24628,24617,24606,24595,
+24584,24573,24562,24552,24541,24530,24519,24508,24497,24486,24475,24464,
+24453,24442,24431,24420,24410,24399,24388,24377,24366,24355,24344,24333,
+24322,24311,24300,24289,24278,24267,24256,24245,24234,24223,24212,24201,
+24189,24178,24167,24156,24145,24134,24123,24112,24101,24090,24079,24068,
+24057,24045,24034,24023,24012,24001,23990,23979,23968,23956,23945,23934,
+23923,23912,23901,23890,23878,23867,23856,23845,23834,23822,23811,23800,
+23789,23778,23766,23755,23744,23733,23721,23710,23699,23688,23676,23665,
+23654,23643,23631,23620,23609,23598,23586,23575,23564,23552,23541,23530,
+23519,23507,23496,23485,23473,23462,23451,23439,23428,23417,23405,23394,
+23382,23371,23360,23348,23337,23326,23314,23303,23291,23280,23269,23257,
+23246,23234,23223,23212,23200,23189,23177,23166,23154,23143,23132,23120,
+23109,23097,23086,23074,23063,23051,23040,23028,23017,23005,22994,22982,
+22971,22959,22948,22936,22925,22913,22902,22890,22879,22867,22856,22844,
+22832,22821,22809,22798,22786,22775,22763,22751,22740,22728,22717,22705,
+22694,22682,22670,22659,22647,22636,22624,22612,22601,22589,22577,22566,
+22554,22542,22531,22519,22508,22496,22484,22473,22461,22449,22438,22426,
+22414,22402,22391,22379,22367,22356,22344,22332,22321,22309,22297,22285,
+22274,22262,22250,22238,22227,22215,22203,22192,22180,22168,22156,22144,
+22133,22121,22109,22097,22086,22074,22062,22050,22038,22027,22015,22003,
+21991,21979,21968,21956,21944,21932,21920,21909,21897,21885,21873,21861,
+21849,21837,21826,21814,21802,21790,21778,21766,21754,21743,21731,21719,
+21707,21695,21683,21671,21659,21647,21636,21624,21612,21600,21588,21576,
+21564,21552,21540,21528,21516,21504,21493,21481,21469,21457,21445,21433,
+21421,21409,21397,21385,21373,21361,21349,21337,21325,21313,21301,21289,
+21277,21265,21253,21241,21229,21217,21205,21193,21181,21169,21157,21145,
+21133,21121,21109,21097,21085,21073,21061,21049,21037,21025,21013,21001,
+20988,20976,20964,20952,20940,20928,20916,20904,20892,20880,20868,20856,
+20844,20831,20819,20807,20795,20783,20771,20759,20747,20735,20723,20710,
+20698,20686,20674,20662,20650,20638,20625,20613,20601,20589,20577,20565,
+20553,20540,20528,20516,20504,20492,20480,20467,20455,20443,20431,20419,
+20407,20394,20382,20370,20358,20346,20333,20321,20309,20297,20285,20272,
+20260,20248,20236,20224,20211,20199,20187,20175,20163,20150,20138,20126,
+20114,20101,20089,20077,20065,20052,20040,20028,20016,20003,19991,19979,
+19967,19954,19942,19930,19918,19905,19893,19881,19868,19856,19844,19832,
+19819,19807,19795,19782,19770,19758,19746,19733,19721,19709,19696,19684,
+19672,19659,19647,19635,19622,19610,19598,19585,19573,19561,19549,19536,
+19524,19512,19499,19487,19474,19462,19450,19437,19425,19413,19400,19388,
+19376,19363,19351,19339,19326,19314,19302,19289,19277,19264,19252,19240,
+19227,19215,19203,19190,19178,19165,19153,19141,19128,19116,19103,19091,
+19079,19066,19054,19041,19029,19017,19004,18992,18979,18967,18955,18942,
+18930,18917,18905,18893,18880,18868,18855,18843,18830,18818,18806,18793,
+18781,18768,18756,18743,18731,18719,18706,18694,18681,18669,18656,18644,
+18631,18619,18607,18594,18582,18569,18557,18544,18532,18519,18507,18494,
+18482,18470,18457,18445,18432,18420,18407,18395,18382,18370,18357,18345,
+18332,18320,18307,18295,18282,18270,18257,18245,18233,18220,18208,18195,
+18183,18170,18158,18145,18133,18120,18108,18095,18083,18070,18058,18045,
+18033,18020,18008,17995,17983,17970,17958,17945,17933,17920,17908,17895,
+17883,17870,17857,17845,17832,17820,17807,17795,17782,17770,17757,17745,
+17732,17720,17707,17695,17682,17670,17657,17645,17632,17620,17607,17594,
+17582,17569,17557,17544,17532,17519,17507,17494,17482,17469,17457,17444,
+17432,17419,17406,17394,17381,17369,17356,17344,17331,17319,17306,17294,
+17281,17268,17256,17243,17231,17218,17206,17193,17181,17168,17155,17143,
+17130,17118,17105,17093,17080,17068,17055,17042,17030,17017,17005,16992,
+16980,16967,16955,16942,16929,16917,16904,16892,16879,16867,16854,16842,
+16829,16816,16804,16791,16779,16766,16754,16741,16728,16716,16703,16691,
+16678,16666,16653,16641,16628,16615,16603,16590,16578,16565,16553,16540,
+16527,16515,16502,16490,16477,16465,16452,16439,16427,16414,16402,16389,
+16375,16363,16350,16337,16325,16312,16300,16287,16275,16262,16249,16237,
+16224,16212,16199,16187,16174,16161,16149,16136,16124,16111,16099,16086,
+16074,16061,16048,16036,16023,16011,15998,15986,15973,15960,15948,15935,
+15923,15910,15898,15885,15873,15860,15847,15835,15822,15810,15797,15785,
+15772,15759,15747,15734,15722,15709,15697,15684,15672,15659,15646,15634,
+15621,15609,15596,15584,15571,15559,15546,15534,15521,15508,15496,15483,
+15471,15458,15446,15433,15421,15408,15395,15383,15370,15358,15345,15333,
+15320,15308,15295,15283,15270,15258,15245,15232,15220,15207,15195,15182,
+15170,15157,15145,15132,15120,15107,15095,15082,15070,15057,15045,15032,
+15019,15007,14994,14982,14969,14957,14944,14932,14919,14907,14894,14882,
+14869,14857,14844,14832,14819,14807,14794,14782,14769,14757,14744,14732,
+14719,14707,14694,14682,14669,14657,14644,14632,14619,14607,14594,14582,
+14569,14557,14544,14532,14519,14507,14494,14482,14469,14457,14444,14432,
+14419,14407,14395,14382,14370,14357,14345,14332,14320,14307,14295,14282,
+14270,14257,14245,14232,14220,14208,14195,14183,14170,14158,14145,14133,
+14120,14108,14096,14083,14071,14058,14046,14033,14021,14008,13996,13984,
+13971,13959,13946,13934,13921,13909,13897,13884,13872,13859,13847,13835,
+13822,13810,13797,13785,13772,13760,13748,13735,13723,13710,13698,13686,
+13673,13661,13648,13636,13624,13611,13599,13587,13574,13562,13549,13537,
+13525,13512,13500,13488,13475,13463,13450,13438,13426,13413,13401,13389,
+13376,13364,13352,13339,13327,13315,13302,13290,13278,13265,13253,13241,
+13228,13216,13204,13191,13179,13167,13154,13142,13130,13117,13105,13093,
+13080,13068,13056,13043,13031,13019,13007,12994,12982,12970,12957,12945,
+12933,12921,12908,12896,12884,12871,12859,12847,12835,12822,12810,12798,
+12786,12773,12761,12749,12737,12724,12712,12700,12688,12675,12663,12651,
+12639,12626,12614,12602,12590,12577,12565,12553,12541,12529,12516,12504,
+12492,12480,12468,12455,12443,12431,12419,12407,12394,12382,12370,12358,
+12346,12333,12321,12309,12297,12285,12273,12260,12248,12236,12224,12212,
+12200,12188,12175,12163,12151,12139,12127,12115,12103,12090,12078,12066,
+12054,12042,12030,12018,12006,11993,11981,11969,11957,11945,11933,11921,
+11909,11897,11885,11873,11860,11848,11836,11824,11812,11800,11788,11776,
+11764,11752,11740,11728,11716,11704,11692,11680,11668,11656,11644,11631,
+11619,11607,11595,11583,11571,11559,11547,11535,11523,11511,11499,11487,
+11475,11463,11451,11439,11427,11415,11404,11392,11380,11368,11356,11344,
+11332,11320,11308,11296,11284,11272,11260,11248,11236,11224,11212,11200,
+11188,11177,11165,11153,11141,11129,11117,11105,11093,11081,11069,11058,
+11046,11034,11022,11010,10998,10986,10974,10963,10951,10939,10927,10915,
+10903,10892,10880,10868,10856,10844,10832,10821,10809,10797,10785,10773,
+10761,10750,10738,10726,10714,10703,10691,10679,10667,10655,10644,10632,
+10620,10608,10597,10585,10573,10561,10550,10538,10526,10514,10503,10491,
+10479,10467,10456,10444,10432,10421,10409,10397,10386,10374,10362,10350,
+10339,10327,10315,10304,10292,10280,10269,10257,10245,10234,10222,10211,
+10199,10187,10176,10164,10152,10141,10129,10118,10106,10094,10083,10071,
+10060,10048,10036,10025,10013,10002,9990,9978,9967,9955,9944,9932,
+9921,9909,9898,9886,9875,9863,9851,9840,9828,9817,9805,9794,
+9782,9771,9759,9748,9736,9725,9713,9702,9691,9679,9668,9656,
+9645,9633,9622,9610,9599,9587,9576,9565,9553,9542,9530,9519,
+9507,9496,9485,9473,9462,9451,9439,9428,9416,9405,9394,9382,
+9371,9360,9348,9337,9326,9314,9303,9292,9280,9269,9258,9246,
+9235,9224,9212,9201,9190,9178,9167,9156,9145,9133,9122,9111,
+9100,9088,9077,9066,9055,9043,9032,9021,9010,8998,8987,8976,
+8965,8954,8942,8931,8920,8909,8898,8886,8875,8864,8853,8842,
+8831,8820,8808,8797,8786,8775,8764,8753,8742,8730,8719,8708,
+8697,8686,8675,8664,8653,8642,8631,8620,8609,8597,8586,8575,
+8564,8553,8542,8531,8520,8509,8498,8487,8476,8465,8454,8443,
+8432,8421,8410,8399,8388,8377,8366,8355,8344,8333,8323,8312,
+8301,8290,8279,8268,8257,8246,8235,8224,8213,8202,8192,8181,
+8170,8159,8148,8137,8126,8116,8105,8094,8083,8072,8061,8051,
+8040,8029,8018,8007,7996,7986,7975,7964,7953,7943,7932,7921,
+7910,7900,7889,7878,7867,7857,7846,7835,7824,7814,7803,7792,
+7782,7771,7760,7750,7739,7728,7718,7707,7696,7686,7675,7664,
+7654,7643,7632,7622,7611,7601,7590,7579,7569,7558,7548,7537,
+7526,7516,7505,7495,7484,7474,7463,7453,7442,7431,7421,7410,
+7400,7389,7379,7368,7358,7347,7337,7326,7316,7306,7295,7285,
+7274,7264,7253,7243,7232,7222,7212,7201,7191,7180,7170,7160,
+7149,7139,7129,7118,7108,7097,7087,7077,7066,7056,7046,7035,
+7025,7015,7004,6994,6984,6974,6963,6953,6943,6932,6922,6912,
+6902,6891,6881,6871,6861,6851,6840,6830,6820,6810,6800,6789,
+6779,6769,6759,6749,6738,6728,6718,6708,6698,6688,6678,6668,
+6657,6647,6637,6627,6617,6607,6597,6587,6577,6567,6557,6547,
+6536,6526,6516,6506,6496,6486,6476,6466,6456,6446,6436,6426,
+6416,6406,6396,6386,6377,6367,6357,6347,6337,6327,6317,6307,
+6297,6287,6277,6267,6258,6248,6238,6228,6218,6208,6198,6189,
+6179,6169,6159,6149,6139,6130,6120,6110,6100,6090,6081,6071,
+6061,6051,6042,6032,6022,6012,6003,5993,5983,5974,5964,5954,
+5945,5935,5925,5916,5906,5896,5887,5877,5867,5858,5848,5838,
+5829,5819,5810,5800,5790,5781,5771,5762,5752,5743,5733,5723,
+5714,5704,5695,5685,5676,5666,5657,5647,5638,5628,5619,5609,
+5600,5590,5581,5572,5562,5553,5543,5534,5524,5515,5506,5496,
+5487,5477,5468,5459,5449,5440,5431,5421,5412,5403,5393,5384,
+5375,5365,5356,5347,5338,5328,5319,5310,5300,5291,5282,5273,
+5263,5254,5245,5236,5227,5217,5208,5199,5190,5181,5172,5162,
+5153,5144,5135,5126,5117,5108,5098,5089,5080,5071,5062,5053,
+5044,5035,5026,5017,5008,4999,4990,4981,4972,4963,4954,4945,
+4936,4927,4918,4909,4900,4891,4882,4873,4864,4855,4846,4837,
+4828,4819,4810,4801,4791,4783,4774,4765,4756,4747,4738,4729,
+4721,4712,4703,4694,4685,4677,4668,4659,4650,4642,4633,4624,
+4615,4607,4598,4589,4580,4572,4563,4554,4546,4537,4528,4520,
+4511,4502,4494,4485,4476,4468,4459,4450,4442,4433,4425,4416,
+4407,4399,4390,4382,4373,4365,4356,4348,4339,4331,4322,4314,
+4305,4297,4288,4280,4271,4263,4254,4246,4237,4229,4221,4212,
+4204,4195,4187,4179,4170,4162,4153,4145,4137,4128,4120,4112,
+4103,4095,4087,4078,4070,4062,4054,4045,4037,4029,4021,4012,
+4004,3996,3988,3979,3971,3963,3955,3947,3938,3930,3922,3914,
+3906,3898,3890,3881,3873,3865,3857,3849,3841,3833,3825,3817,
+3809,3801,3793,3785,3776,3768,3760,3752,3744,3736,3728,3720,
+3713,3705,3697,3689,3681,3673,3665,3657,3649,3641,3633,3625,
+3617,3610,3602,3594,3586,3578,3570,3563,3555,3547,3539,3531,
+3524,3516,3508,3500,3492,3485,3477,3469,3461,3454,3446,3438,
+3431,3423,3415,3408,3400,3392,3385,3377,3369,3362,3354,3346,
+3339,3331,3324,3316,3309,3301,3293,3286,3278,3271,3263,3256,
+3248,3241,3233,3226,3218,3211,3203,3196,3188,3181,3173,3166,
+3159,3151,3144,3136,3129,3122,3114,3107,3100,3092,3085,3078,
+3070,3063,3056,3048,3041,3034,3026,3019,3012,3005,2997,2990,
+2983,2976,2968,2961,2954,2947,2940,2932,2925,2918,2911,2904,
+2897,2890,2882,2875,2868,2861,2854,2847,2840,2833,2826,2819,
+2812,2805,2798,2791,2784,2777,2770,2763,2756,2749,2742,2735,
+2728,2721,2714,2707,2700,2693,2686,2679,2672,2666,2659,2652,
+2645,2638,2631,2625,2618,2611,2604,2597,2591,2584,2577,2570,
+2563,2557,2550,2543,2537,2530,2523,2516,2510,2503,2496,2490,
+2483,2476,2470,2463,2457,2450,2443,2437,2430,2424,2417,2410,
+2404,2397,2391,2384,2378,2371,2365,2358,2352,2345,2339,2332,
+2326,2319,2313,2307,2300,2294,2287,2281,2274,2268,2262,2255,
+2249,2243,2236,2230,2224,2217,2211,2205,2198,2192,2186,2180,
+2173,2167,2161,2155,2148,2142,2136,2130,2124,2117,2111,2105,
+2099,2093,2087,2080,2074,2068,2062,2056,2050,2044,2038,2032,
+2026,2020,2014,2008,2002,1996,1990,1984,1978,1972,1966,1960,
+1954,1948,1942,1936,1930,1924,1918,1912,1906,1900,1895,1889,
+1883,1877,1871,1865,1860,1854,1848,1842,1836,1831,1825,1819,
+1813,1808,1802,1796,1790,1785,1779,1773,1768,1762,1756,1751,
+1745,1739,1734,1728,1722,1717,1711,1706,1700,1695,1689,1683,
+1678,1672,1667,1661,1656,1650,1645,1639,1634,1628,1623,1617,
+1612,1607,1601,1596,1590,1585,1580,1574,1569,1563,1558,1553,
+1547,1542,1537,1531,1526,1521,1516,1510,1505,1500,1495,1489,
+1484,1479,1474,1468,1463,1458,1453,1448,1443,1437,1432,1427,
+1422,1417,1412,1407,1402,1397,1391,1386,1381,1376,1371,1366,
+1361,1356,1351,1346,1341,1336,1331,1326,1321,1316,1312,1307,
+1302,1297,1292,1287,1282,1277,1272,1268,1263,1258,1253,1248,
+1243,1239,1234,1229,1224,1220,1215,1210,1205,1201,1196,1191,
+1186,1182,1177,1172,1168,1163,1158,1154,1149,1145,1140,1135,
+1131,1126,1122,1117,1113,1108,1103,1099,1094,1090,1085,1081,
+1076,1072,1067,1063,1059,1054,1050,1045,1041,1036,1032,1028,
+1023,1019,1015,1010,1006,1002,997,993,989,984,980,976,
+972,967,963,959,955,950,946,942,938,934,929,925,
+921,917,913,909,904,900,896,892,888,884,880,876,
+872,868,864,860,856,852,848,844,840,836,832,828,
+824,820,816,812,808,804,801,797,793,789,785,781,
+777,774,770,766,762,758,755,751,747,743,740,736,
+732,729,725,721,717,714,710,706,703,699,696,692,
+688,685,681,678,674,670,667,663,660,656,653,649,
+646,642,639,635,632,628,625,622,618,615,611,608,
+605,601,598,594,591,588,584,581,578,574,571,568,
+565,561,558,555,552,548,545,542,539,536,532,529,
+526,523,520,517,514,510,507,504,501,498,495,492,
+489,486,483,480,477,474,471,468,465,462,459,456,
+453,450,447,444,441,438,436,433,430,427,424,421,
+418,416,413,410,407,404,402,399,396,393,391,388,
+385,383,380,377,375,372,369,367,364,361,359,356,
+353,351,348,346,343,341,338,336,333,331,328,326,
+323,321,318,316,313,311,308,306,303,301,299,296,
+294,292,289,287,285,282,280,278,275,273,271,268,
+266,264,262,259,257,255,253,251,248,246,244,242,
+240,238,236,233,231,229,227,225,223,221,219,217,
+215,213,211,209,207,205,203,201,199,197,195,193,
+191,189,187,186,184,182,180,178,176,174,173,171,
+169,167,165,164,162,160,158,157,155,153,151,150,
+148,146,145,143,141,140,138,137,135,133,132,130,
+129,127,125,124,122,121,119,118,116,115,113,112,
+110,109,108,106,105,103,102,101,99,98,96,95,
+94,92,91,90,88,87,86,85,83,82,81,80,
+78,77,76,75,74,72,71,70,69,68,67,65,
+64,63,62,61,60,59,58,57,56,55,54,53,
+52,51,50,49,48,47,46,45,44,43,42,41,
+41,40,39,38,37,36,35,35,34,33,32,31,
+31,30,29,28,28,27,26,26,25,24,24,23,
+22,22,21,20,20,19,19,18,17,17,16,16,
+15,15,14,14,13,13,12,12,11,11,10,10,
+9,9,9,8,8,8,7,7,6,6,6,5,
+5,5,5,4,4,4,4,3,3,3,3,2,
+2,2,2,2,2,1,1,1,1,1,1,1,
+1,1,1,1,1,1,1,1};
+const int32_t hann_4096 [] = {1,1,1,1,1,1,1,1,2,2,2,3,
+3,4,4,5,5,6,7,7,8,9,10,11,
+12,13,14,15,16,17,18,19,20,21,23,24,
+25,27,28,30,31,33,34,36,38,40,41,43,
+45,47,49,51,53,55,57,59,61,63,65,68,
+70,72,75,77,79,82,84,87,90,92,95,98,
+100,103,106,109,112,115,118,121,124,127,130,133,
+136,140,143,146,150,153,156,160,163,167,171,174,
+178,182,185,189,193,197,201,205,209,213,217,221,
+225,229,233,237,242,246,250,255,259,264,268,273,
+277,282,287,291,296,301,306,310,315,320,325,330,
+335,340,345,351,356,361,366,372,377,382,388,393,
+399,404,410,415,421,427,432,438,444,450,456,461,
+467,473,479,485,492,498,504,510,516,523,529,535,
+542,548,554,561,567,574,581,587,594,601,607,614,
+621,628,635,642,649,656,663,670,677,684,691,699,
+706,713,721,728,735,743,750,758,766,773,781,788,
+796,804,812,820,827,835,843,851,859,867,875,884,
+892,900,908,916,925,933,941,950,958,967,975,984,
+992,1001,1010,1018,1027,1036,1045,1054,1062,1071,1080,1089,
+1098,1107,1117,1126,1135,1144,1153,1163,1172,1181,1191,1200,
+1209,1219,1228,1238,1248,1258,1268,1277,1287,1297,1307,1316,
+1326,1336,1346,1356,1366,1376,1386,1397,1407,1417,1427,1437,
+1448,1458,1468,1479,1489,1500,1510,1521,1531,1542,1553,1563,
+1574,1585,1596,1607,1617,1628,1639,1650,1661,1672,1683,1695,
+1706,1717,1728,1739,1751,1762,1773,1785,1796,1808,1819,1831,
+1842,1854,1865,1877,1889,1900,1912,1924,1936,1948,1960,1972,
+1984,1996,2008,2020,2032,2044,2056,2068,2080,2093,2105,2117,
+2130,2142,2155,2167,2180,2192,2205,2217,2230,2243,2255,2268,
+2281,2294,2307,2319,2332,2345,2358,2371,2384,2397,2410,2424,
+2437,2450,2463,2476,2490,2503,2516,2530,2543,2557,2570,2584,
+2597,2611,2625,2638,2652,2666,2679,2693,2707,2721,2735,2749,
+2763,2777,2791,2805,2819,2833,2847,2861,2875,2890,2904,2918,
+2932,2947,2961,2976,2990,3005,3019,3034,3048,3063,3078,3092,
+3107,3122,3136,3151,3166,3181,3196,3211,3226,3241,3256,3271,
+3286,3301,3316,3331,3346,3362,3377,3392,3408,3423,3438,3454,
+3469,3485,3500,3516,3531,3547,3563,3578,3594,3610,3625,3641,
+3657,3673,3689,3705,3720,3736,3752,3768,3785,3801,3817,3833,
+3849,3865,3881,3898,3914,3930,3947,3963,3979,3996,4012,4029,
+4045,4062,4078,4095,4112,4128,4145,4162,4179,4195,4212,4229,
+4246,4263,4280,4297,4314,4331,4348,4365,4382,4399,4416,4433,
+4450,4468,4485,4502,4520,4537,4554,4572,4589,4607,4624,4642,
+4659,4677,4694,4712,4729,4747,4765,4783,4801,4819,4837,4855,
+4873,4891,4909,4927,4945,4963,4981,4999,5017,5035,5053,5071,
+5089,5108,5126,5144,5162,5181,5199,5217,5236,5254,5273,5291,
+5310,5328,5347,5365,5384,5403,5421,5440,5459,5477,5496,5515,
+5534,5553,5572,5590,5609,5628,5647,5666,5685,5704,5723,5743,
+5762,5781,5800,5819,5838,5858,5877,5896,5916,5935,5954,5974,
+5993,6012,6032,6051,6071,6090,6110,6130,6149,6169,6189,6208,
+6228,6248,6267,6287,6307,6327,6347,6367,6386,6406,6426,6446,
+6466,6486,6506,6526,6547,6567,6587,6607,6627,6647,6668,6688,
+6708,6728,6749,6769,6789,6810,6830,6851,6871,6891,6912,6932,
+6953,6974,6994,7015,7035,7056,7077,7097,7118,7139,7160,7180,
+7201,7222,7243,7264,7285,7306,7326,7347,7368,7389,7410,7431,
+7453,7474,7495,7516,7537,7558,7579,7601,7622,7643,7664,7686,
+7707,7728,7750,7771,7792,7814,7835,7857,7878,7900,7921,7943,
+7964,7986,8007,8029,8051,8072,8094,8116,8137,8159,8181,8202,
+8224,8246,8268,8290,8312,8333,8355,8377,8399,8421,8443,8465,
+8487,8509,8531,8553,8575,8597,8620,8642,8664,8686,8708,8730,
+8753,8775,8797,8820,8842,8864,8886,8909,8931,8954,8976,8998,
+9021,9043,9066,9088,9111,9133,9156,9178,9201,9224,9246,9269,
+9292,9314,9337,9360,9382,9405,9428,9451,9473,9496,9519,9542,
+9565,9587,9610,9633,9656,9679,9702,9725,9748,9771,9794,9817,
+9840,9863,9886,9909,9932,9955,9978,10002,10025,10048,10071,10094,
+10119,10142,10165,10189,10212,10235,10259,10282,10305,10329,10352,10375,
+10399,10422,10446,10469,10492,10516,10539,10563,10586,10610,10633,10657,
+10680,10704,10728,10751,10775,10798,10822,10846,10869,10893,10917,10940,
+10964,10988,11012,11035,11059,11083,11107,11130,11154,11178,11202,11226,
+11250,11273,11297,11321,11345,11369,11393,11417,11441,11465,11489,11513,
+11537,11561,11585,11609,11633,11657,11681,11705,11729,11753,11778,11802,
+11826,11850,11874,11898,11922,11947,11971,11995,12019,12043,12068,12092,
+12116,12140,12165,12189,12213,12238,12262,12286,12311,12335,12359,12384,
+12408,12432,12457,12481,12506,12530,12555,12579,12603,12628,12652,12677,
+12701,12726,12750,12775,12799,12824,12848,12873,12898,12922,12947,12971,
+12996,13020,13045,13070,13094,13119,13143,13168,13193,13217,13242,13267,
+13291,13316,13341,13366,13390,13415,13440,13464,13489,13514,13539,13563,
+13588,13613,13638,13662,13687,13712,13737,13762,13786,13811,13836,13861,
+13886,13911,13935,13960,13985,14010,14035,14060,14085,14110,14134,14159,
+14184,14209,14234,14259,14284,14309,14334,14359,14384,14409,14433,14458,
+14483,14508,14533,14558,14583,14608,14633,14658,14683,14708,14733,14758,
+14783,14808,14833,14858,14883,14908,14933,14958,14983,15009,15034,15059,
+15084,15109,15134,15159,15184,15209,15234,15259,15284,15309,15334,15359,
+15385,15410,15435,15460,15485,15510,15535,15560,15585,15610,15635,15661,
+15686,15711,15736,15761,15786,15811,15836,15862,15887,15912,15937,15962,
+15987,16012,16037,16063,16088,16113,16138,16163,16188,16213,16238,16264,
+16289,16314,16339,16364,16391,16416,16441,16466,16491,16516,16542,16567,
+16592,16617,16642,16667,16692,16717,16743,16768,16793,16818,16843,16868,
+16893,16918,16944,16969,16994,17019,17044,17069,17094,17119,17144,17170,
+17195,17220,17245,17270,17295,17320,17345,17370,17395,17421,17446,17471,
+17496,17521,17546,17571,17596,17621,17646,17671,17696,17721,17746,17771,
+17796,17822,17847,17872,17897,17922,17947,17972,17997,18022,18047,18072,
+18097,18122,18147,18172,18197,18222,18247,18272,18297,18321,18346,18371,
+18396,18421,18446,18471,18496,18521,18546,18571,18596,18621,18645,18670,
+18695,18720,18745,18770,18795,18820,18844,18869,18894,18919,18944,18969,
+18993,19018,19043,19068,19093,19117,19142,19167,19192,19216,19241,19266,
+19291,19315,19340,19365,19390,19414,19439,19464,19488,19513,19538,19562,
+19587,19612,19636,19661,19686,19710,19735,19759,19784,19809,19833,19858,
+19882,19907,19931,19956,19980,20005,20029,20054,20078,20103,20127,20152,
+20176,20201,20225,20250,20274,20298,20323,20347,20372,20396,20420,20445,
+20469,20493,20518,20542,20566,20591,20615,20639,20663,20688,20712,20736,
+20760,20785,20809,20833,20857,20881,20906,20930,20954,20978,21002,21026,
+21050,21074,21098,21122,21147,21171,21195,21219,21243,21267,21291,21315,
+21339,21363,21386,21410,21434,21458,21482,21506,21530,21554,21578,21601,
+21625,21649,21673,21697,21720,21744,21768,21792,21815,21839,21863,21886,
+21910,21934,21957,21981,22005,22028,22052,22075,22099,22122,22146,22169,
+22193,22216,22240,22263,22287,22310,22334,22357,22381,22404,22427,22451,
+22474,22497,22521,22544,22567,22590,22614,22637,22662,22685,22708,22731,
+22754,22778,22801,22824,22847,22870,22893,22916,22939,22962,22985,23008,
+23031,23054,23077,23100,23123,23146,23169,23192,23214,23237,23260,23283,
+23306,23328,23351,23374,23397,23419,23442,23465,23487,23510,23533,23555,
+23578,23600,23623,23646,23668,23691,23713,23735,23758,23780,23803,23825,
+23848,23870,23892,23915,23937,23959,23982,24004,24026,24048,24070,24093,
+24115,24137,24159,24181,24203,24225,24247,24269,24291,24313,24335,24357,
+24379,24401,24423,24445,24467,24489,24511,24532,24554,24576,24598,24620,
+24641,24663,24685,24706,24728,24750,24771,24793,24814,24836,24857,24879,
+24900,24922,24943,24965,24986,25007,25029,25050,25071,25093,25114,25135,
+25157,25178,25199,25220,25241,25262,25284,25305,25326,25347,25368,25389,
+25410,25431,25452,25473,25493,25514,25535,25556,25577,25598,25618,25639,
+25660,25681,25701,25722,25743,25763,25784,25804,25825,25845,25866,25886,
+25907,25927,25948,25968,25989,26009,26029,26050,26070,26090,26110,26131,
+26151,26171,26191,26211,26231,26251,26271,26291,26311,26331,26351,26371,
+26391,26411,26431,26451,26471,26490,26510,26530,26550,26569,26589,26609,
+26628,26648,26668,26687,26707,26726,26746,26765,26784,26804,26823,26843,
+26862,26881,26901,26920,26939,26958,26977,26997,27016,27035,27054,27073,
+27092,27111,27130,27149,27168,27187,27206,27225,27243,27262,27281,27300,
+27318,27337,27356,27375,27393,27412,27430,27449,27467,27486,27504,27523,
+27541,27560,27578,27596,27615,27633,27651,27669,27688,27706,27724,27742,
+27760,27778,27796,27814,27832,27850,27868,27886,27904,27922,27940,27958,
+27976,27994,28012,28030,28047,28065,28082,28100,28118,28135,28153,28170,
+28188,28205,28222,28240,28257,28274,28292,28309,28326,28343,28360,28378,
+28395,28412,28429,28446,28463,28480,28497,28514,28531,28547,28564,28581,
+28598,28615,28631,28648,28665,28681,28698,28714,28731,28747,28764,28780,
+28797,28813,28830,28846,28862,28878,28895,28911,28927,28943,28959,28975,
+28992,29008,29024,29040,29055,29071,29087,29103,29119,29135,29151,29166,
+29182,29198,29213,29229,29245,29260,29276,29291,29307,29322,29337,29353,
+29368,29383,29399,29414,29429,29444,29460,29475,29490,29505,29520,29535,
+29550,29565,29580,29595,29609,29624,29639,29654,29669,29683,29698,29713,
+29727,29742,29756,29771,29785,29800,29814,29828,29843,29857,29871,29886,
+29900,29914,29928,29942,29956,29971,29985,29999,30013,30026,30040,30054,
+30068,30082,30096,30109,30123,30137,30150,30164,30178,30191,30205,30218,
+30232,30245,30258,30272,30285,30298,30312,30325,30338,30351,30364,30377,
+30390,30403,30416,30429,30442,30455,30468,30481,30494,30506,30519,30532,
+30545,30557,30570,30582,30595,30607,30620,30632,30645,30657,30669,30682,
+30694,30706,30718,30730,30743,30755,30767,30779,30791,30803,30815,30826,
+30838,30850,30862,30874,30885,30897,30909,30920,30932,30943,30955,30966,
+30978,30989,31001,31012,31023,31035,31046,31057,31068,31079,31090,31101,
+31113,31124,31134,31145,31156,31167,31178,31189,31199,31210,31221,31232,
+31242,31253,31263,31274,31284,31295,31305,31315,31326,31336,31346,31357,
+31367,31377,31387,31397,31407,31417,31427,31437,31447,31457,31467,31476,
+31486,31496,31506,31515,31526,31535,31545,31554,31564,31573,31583,31592,
+31601,31611,31620,31629,31638,31647,31656,31666,31675,31684,31693,31702,
+31710,31719,31728,31737,31746,31754,31763,31772,31780,31789,31797,31806,
+31814,31823,31831,31840,31848,31856,31865,31873,31881,31889,31897,31905,
+31913,31921,31929,31937,31945,31953,31961,31968,31976,31984,31992,31999,
+32007,32014,32022,32029,32037,32044,32052,32059,32066,32073,32081,32088,
+32095,32102,32109,32116,32123,32130,32137,32144,32151,32158,32164,32171,
+32178,32185,32191,32198,32204,32211,32217,32224,32230,32237,32243,32249,
+32255,32262,32268,32274,32280,32286,32292,32298,32304,32310,32316,32322,
+32328,32333,32339,32345,32351,32356,32362,32367,32373,32378,32384,32389,
+32394,32400,32405,32410,32416,32421,32426,32431,32436,32441,32446,32451,
+32456,32461,32466,32470,32475,32480,32484,32489,32494,32498,32503,32507,
+32512,32516,32521,32525,32529,32533,32538,32542,32546,32550,32554,32558,
+32562,32566,32570,32574,32578,32582,32585,32589,32593,32596,32600,32604,
+32607,32611,32614,32618,32621,32624,32628,32631,32634,32637,32640,32644,
+32647,32650,32653,32656,32659,32661,32664,32667,32670,32673,32675,32678,
+32681,32683,32686,32688,32691,32693,32695,32698,32700,32702,32705,32707,
+32709,32711,32713,32715,32717,32719,32721,32723,32725,32727,32728,32730,
+32732,32734,32735,32737,32738,32740,32741,32743,32744,32745,32747,32748,
+32749,32750,32752,32753,32754,32755,32756,32757,32758,32759,32760,32760,
+32761,32762,32763,32763,32764,32764,32765,32765,32766,32766,32767,32767,
+32767,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,
+32768,32768,32768,32767,32767,32767,32766,32766,32765,32765,32764,32764,
+32763,32763,32762,32761,32760,32760,32759,32758,32757,32756,32755,32754,
+32753,32752,32751,32749,32748,32747,32746,32744,32743,32741,32740,32738,
+32737,32735,32734,32732,32730,32729,32727,32725,32723,32721,32719,32717,
+32715,32713,32711,32709,32707,32705,32703,32700,32698,32696,32693,32691,
+32688,32686,32683,32681,32678,32675,32673,32670,32667,32664,32662,32659,
+32656,32653,32650,32647,32644,32641,32637,32634,32631,32628,32624,32621,
+32618,32614,32611,32607,32604,32600,32597,32593,32589,32586,32582,32578,
+32574,32570,32566,32562,32558,32554,32550,32546,32542,32538,32534,32529,
+32525,32521,32516,32512,32508,32503,32499,32494,32489,32485,32480,32475,
+32471,32466,32461,32456,32451,32446,32441,32436,32431,32426,32421,32416,
+32411,32405,32400,32395,32389,32384,32379,32373,32368,32362,32357,32351,
+32345,32340,32334,32328,32322,32316,32311,32305,32299,32293,32287,32281,
+32274,32268,32262,32256,32250,32243,32237,32231,32224,32218,32211,32205,
+32198,32192,32185,32178,32172,32165,32158,32151,32144,32138,32131,32124,
+32117,32110,32103,32095,32088,32081,32074,32067,32059,32052,32045,32037,
+32030,32022,32015,32007,32000,31992,31984,31977,31969,31961,31953,31946,
+31938,31930,31922,31914,31906,31898,31890,31881,31873,31865,31857,31848,
+31840,31832,31823,31815,31807,31798,31789,31781,31772,31764,31755,31746,
+31737,31729,31720,31711,31702,31693,31684,31675,31666,31657,31648,31639,
+31630,31620,31611,31602,31592,31583,31574,31564,31555,31545,31536,31526,
+31516,31506,31497,31487,31477,31467,31457,31448,31438,31428,31418,31408,
+31398,31388,31378,31367,31357,31347,31337,31326,31316,31306,31295,31285,
+31274,31264,31253,31243,31232,31222,31211,31200,31189,31179,31168,31157,
+31146,31135,31124,31113,31102,31091,31080,31069,31058,31047,31035,31024,
+31013,31001,30990,30979,30967,30956,30944,30933,30921,30909,30898,30886,
+30874,30863,30851,30839,30827,30815,30803,30791,30779,30767,30755,30743,
+30731,30719,30707,30695,30682,30670,30658,30645,30633,30621,30608,30596,
+30583,30571,30558,30545,30533,30520,30507,30495,30482,30469,30456,30443,
+30430,30417,30404,30391,30378,30365,30352,30339,30326,30312,30299,30286,
+30273,30259,30246,30232,30219,30206,30192,30178,30165,30151,30138,30124,
+30110,30097,30083,30069,30055,30041,30027,30013,29999,29985,29971,29957,
+29943,29929,29915,29901,29887,29872,29858,29844,29829,29815,29801,29786,
+29772,29757,29743,29728,29713,29699,29684,29669,29655,29640,29625,29610,
+29596,29581,29566,29551,29536,29521,29506,29491,29476,29460,29445,29430,
+29415,29400,29384,29369,29354,29338,29323,29308,29292,29277,29261,29245,
+29230,29214,29199,29183,29167,29152,29136,29120,29104,29088,29072,29056,
+29041,29025,29009,28993,28976,28960,28944,28928,28912,28896,28879,28863,
+28847,28831,28814,28798,28781,28765,28748,28732,28715,28699,28682,28666,
+28649,28632,28616,28599,28582,28565,28548,28532,28515,28498,28481,28464,
+28447,28430,28413,28396,28379,28362,28344,28327,28310,28293,28275,28258,
+28241,28223,28206,28189,28171,28154,28136,28119,28101,28084,28066,28048,
+28031,28013,27995,27978,27959,27941,27923,27905,27887,27869,27851,27833,
+27815,27797,27779,27761,27743,27725,27707,27689,27671,27652,27634,27616,
+27597,27579,27561,27542,27524,27506,27487,27469,27450,27431,27413,27394,
+27376,27357,27338,27320,27301,27282,27263,27245,27226,27207,27188,27169,
+27150,27131,27112,27093,27074,27055,27036,27017,26998,26979,26959,26940,
+26921,26902,26882,26863,26844,26824,26805,26786,26766,26747,26727,26708,
+26688,26669,26649,26630,26610,26590,26571,26551,26531,26511,26492,26472,
+26452,26432,26412,26392,26373,26353,26333,26313,26293,26273,26253,26233,
+26212,26192,26172,26152,26132,26112,26091,26071,26051,26031,26010,25990,
+25969,25949,25929,25908,25888,25867,25847,25826,25806,25785,25765,25744,
+25723,25703,25682,25661,25640,25620,25599,25578,25557,25537,25516,25495,
+25474,25453,25432,25411,25390,25369,25348,25327,25306,25285,25264,25243,
+25221,25200,25179,25158,25137,25115,25094,25073,25051,25030,25009,24987,
+24966,24945,24923,24902,24880,24859,24837,24816,24794,24773,24751,24729,
+24708,24686,24664,24643,24621,24599,24577,24556,24534,24512,24490,24468,
+24446,24425,24403,24381,24359,24337,24315,24293,24271,24249,24227,24205,
+24183,24160,24138,24116,24094,24072,24050,24027,24005,23983,23961,23938,
+23916,23894,23871,23849,23827,23804,23782,23759,23737,23714,23692,23669,
+23647,23624,23602,23579,23557,23534,23511,23489,23466,23443,23421,23398,
+23375,23353,23330,23307,23284,23262,23239,23216,23193,23170,23147,23124,
+23101,23078,23056,23033,23010,22987,22964,22941,22918,22894,22871,22848,
+22825,22802,22779,22756,22733,22709,22686,22663,22638,22615,22592,22569,
+22545,22522,22499,22475,22452,22429,22405,22382,22359,22335,22312,22288,
+22265,22241,22218,22194,22171,22147,22124,22100,22077,22053,22030,22006,
+21982,21959,21935,21911,21888,21864,21840,21817,21793,21769,21746,21722,
+21698,21674,21650,21627,21603,21579,21555,21531,21507,21484,21460,21436,
+21412,21388,21364,21340,21316,21292,21268,21244,21220,21196,21172,21148,
+21124,21100,21076,21052,21028,21004,20979,20955,20931,20907,20883,20859,
+20835,20810,20786,20762,20738,20713,20689,20665,20641,20616,20592,20568,
+20544,20519,20495,20471,20446,20422,20397,20373,20349,20324,20300,20276,
+20251,20227,20202,20178,20153,20129,20104,20080,20055,20031,20006,19982,
+19957,19933,19908,19884,19859,19835,19810,19785,19761,19736,19712,19687,
+19662,19638,19613,19589,19564,19539,19515,19490,19465,19441,19416,19391,
+19366,19342,19317,19292,19268,19243,19218,19193,19169,19144,19119,19094,
+19069,19045,19020,18995,18970,18945,18921,18896,18871,18846,18821,18796,
+18771,18747,18722,18697,18672,18647,18622,18597,18572,18547,18523,18498,
+18473,18448,18423,18398,18373,18348,18323,18298,18273,18248,18223,18198,
+18173,18148,18123,18098,18073,18048,18023,17998,17973,17948,17923,17898,
+17873,17848,17823,17798,17773,17748,17723,17698,17673,17648,17623,17598,
+17573,17547,17522,17497,17472,17447,17422,17397,17372,17347,17322,17297,
+17272,17246,17221,17196,17171,17146,17121,17096,17071,17046,17021,16995,
+16970,16945,16920,16895,16870,16845,16820,16794,16769,16744,16719,16694,
+16669,16644,16619,16593,16568,16543,16518,16493,16468,16443,16417,16392,
+16366,16341,16315,16290,16265,16240,16215,16190,16165,16139,16114,16089,
+16064,16039,16014,15989,15964,15938,15913,15888,15863,15838,15813,15788,
+15763,15738,15712,15687,15662,15637,15612,15587,15562,15537,15512,15486,
+15461,15436,15411,15386,15361,15336,15311,15286,15261,15236,15211,15185,
+15160,15135,15110,15085,15060,15035,15010,14985,14960,14935,14910,14885,
+14860,14835,14810,14785,14760,14735,14710,14685,14660,14635,14610,14585,
+14560,14535,14510,14485,14460,14435,14410,14385,14360,14335,14310,14285,
+14260,14236,14211,14186,14161,14136,14111,14086,14061,14036,14012,13987,
+13962,13937,13912,13887,13862,13838,13813,13788,13763,13738,13714,13689,
+13664,13639,13614,13590,13565,13540,13515,13491,13466,13441,13416,13392,
+13367,13342,13318,13293,13268,13244,13219,13194,13170,13145,13120,13096,
+13071,13047,13022,12997,12973,12948,12924,12899,12874,12850,12825,12801,
+12776,12752,12727,12703,12678,12654,12629,12605,12581,12556,12532,12507,
+12483,12458,12434,12410,12385,12361,12337,12312,12288,12263,12239,12215,
+12191,12166,12142,12118,12093,12069,12045,12021,11997,11972,11948,11924,
+11900,11876,11851,11827,11803,11779,11755,11731,11707,11683,11659,11634,
+11610,11586,11562,11538,11514,11490,11466,11442,11418,11395,11371,11347,
+11323,11299,11275,11251,11227,11203,11180,11156,11132,11108,11084,11061,
+11037,11013,10989,10966,10942,10918,10894,10871,10847,10824,10800,10776,
+10753,10729,10705,10682,10658,10635,10611,10588,10564,10541,10517,10494,
+10470,10447,10424,10400,10377,10353,10330,10307,10283,10260,10237,10213,
+10190,10167,10144,10120,10096,10073,10049,10026,10003,9980,9957,9934,
+9911,9887,9864,9841,9818,9795,9772,9749,9726,9703,9680,9658,
+9635,9612,9589,9566,9543,9520,9498,9475,9452,9429,9406,9384,
+9361,9338,9316,9293,9270,9248,9225,9202,9180,9157,9135,9112,
+9090,9067,9045,9022,9000,8977,8955,8933,8910,8888,8866,8843,
+8821,8799,8776,8754,8732,8710,8687,8665,8643,8621,8599,8577,
+8555,8533,8511,8489,8467,8445,8423,8401,8379,8357,8335,8313,
+8291,8269,8247,8226,8204,8182,8160,8139,8117,8095,8074,8052,
+8030,8009,7987,7965,7944,7922,7901,7879,7858,7836,7815,7794,
+7772,7751,7730,7708,7687,7666,7644,7623,7602,7581,7559,7538,
+7517,7496,7475,7454,7433,7412,7391,7370,7349,7328,7307,7286,
+7265,7244,7223,7203,7182,7161,7140,7119,7099,7078,7057,7037,
+7016,6995,6975,6954,6934,6913,6893,6872,6852,6831,6811,6791,
+6770,6750,6730,6709,6689,6669,6649,6628,6608,6588,6568,6548,
+6528,6508,6488,6468,6448,6428,6408,6388,6368,6348,6328,6308,
+6288,6269,6249,6229,6209,6190,6170,6150,6131,6111,6092,6072,
+6053,6033,6014,5994,5975,5955,5936,5917,5897,5878,5859,5840,
+5820,5801,5782,5763,5744,5725,5706,5686,5667,5648,5629,5611,
+5592,5573,5554,5535,5516,5497,5479,5460,5441,5422,5404,5385,
+5367,5348,5329,5311,5292,5274,5255,5237,5219,5200,5182,5164,
+5145,5127,5109,5090,5072,5054,5036,5018,5000,4982,4964,4946,
+4928,4910,4892,4874,4856,4838,4820,4803,4784,4766,4748,4731,
+4713,4695,4678,4660,4643,4625,4608,4590,4573,4555,4538,4521,
+4503,4486,4469,4451,4434,4417,4400,4383,4366,4349,4332,4315,
+4298,4281,4264,4247,4230,4213,4196,4180,4163,4146,4129,4113,
+4096,4079,4063,4046,4030,4013,3997,3980,3964,3948,3931,3915,
+3899,3882,3866,3850,3834,3818,3802,3786,3769,3753,3737,3721,
+3706,3690,3674,3658,3642,3626,3611,3595,3579,3564,3548,3532,
+3517,3501,3486,3470,3455,3439,3424,3409,3393,3378,3363,3347,
+3332,3317,3302,3287,3272,3257,3242,3227,3212,3197,3182,3167,
+3152,3137,3123,3108,3093,3078,3064,3049,3035,3020,3005,2991,
+2977,2962,2948,2933,2919,2905,2890,2876,2862,2848,2834,2820,
+2805,2791,2777,2763,2749,2736,2722,2708,2694,2680,2666,2653,
+2639,2625,2612,2598,2585,2571,2558,2544,2531,2517,2504,2491,
+2477,2464,2451,2438,2424,2411,2398,2385,2372,2359,2346,2333,
+2320,2307,2294,2282,2269,2256,2243,2231,2218,2205,2193,2180,
+2168,2155,2143,2131,2118,2106,2094,2081,2069,2057,2045,2032,
+2020,2008,1996,1984,1972,1960,1948,1937,1925,1913,1901,1889,
+1878,1866,1854,1843,1831,1820,1808,1797,1785,1774,1763,1751,
+1740,1729,1718,1706,1695,1684,1673,1662,1651,1640,1629,1618,
+1607,1596,1586,1575,1564,1553,1543,1532,1522,1511,1500,1490,
+1480,1469,1459,1448,1438,1428,1418,1407,1397,1387,1377,1367,
+1357,1347,1337,1327,1317,1307,1297,1288,1278,1268,1259,1249,
+1239,1229,1220,1210,1201,1191,1182,1172,1163,1154,1145,1135,
+1126,1117,1108,1099,1090,1081,1072,1063,1054,1045,1036,1028,
+1019,1010,1002,993,984,976,967,959,950,942,934,925,
+917,909,900,892,884,876,868,860,852,844,836,828,
+820,812,804,797,789,781,774,766,758,751,743,736,
+729,721,714,706,699,692,685,678,670,663,656,649,
+642,635,628,622,615,608,601,594,588,581,574,568,
+561,555,548,542,536,529,523,517,510,504,498,492,
+486,480,474,468,462,456,450,444,438,433,427,421,
+416,410,404,399,393,388,383,377,372,367,361,356,
+351,346,341,336,331,326,321,316,311,306,301,296,
+292,287,282,278,273,268,264,259,255,251,246,242,
+238,233,229,225,221,217,213,209,205,201,197,193,
+189,186,182,178,174,171,167,164,160,157,153,150,
+146,143,140,137,133,130,127,124,121,118,115,112,
+109,106,103,101,98,95,92,90,87,85,82,80,
+77,75,72,70,68,65,63,61,59,57,55,53,
+51,49,47,45,43,41,40,38,36,35,33,31,
+30,28,27,26,24,23,22,20,19,18,17,16,
+15,14,13,12,11,10,9,8,8,7,6,5,
+5,4,4,3,3,2,2,2,1,1,1,1,
+1,1,1,1};
+const int32_t hann_2048 [] = {1,1,1,1,2,2,3,4,5,7,8,10,
+12,14,16,18,20,23,25,28,31,34,38,41,
+45,49,53,57,61,65,70,75,79,84,90,95,
+100,106,112,118,124,130,136,143,150,156,163,171,
+178,185,193,201,209,217,225,233,242,250,259,268,
+277,287,296,306,316,326,336,346,356,367,377,388,
+399,410,421,433,444,456,468,480,492,504,517,529,
+542,555,568,581,594,608,622,635,649,663,678,692,
+706,721,736,751,766,781,797,812,828,844,860,876,
+892,909,925,942,959,976,993,1010,1028,1045,1063,1081,
+1099,1117,1135,1154,1172,1191,1210,1229,1249,1268,1288,1307,
+1327,1347,1367,1387,1407,1428,1448,1469,1490,1511,1532,1553,
+1575,1596,1618,1640,1662,1684,1706,1729,1751,1774,1797,1820,
+1843,1866,1889,1913,1937,1960,1984,2008,2032,2057,2081,2106,
+2131,2155,2180,2205,2231,2256,2282,2307,2333,2359,2385,2411,
+2438,2464,2491,2517,2544,2571,2598,2625,2653,2680,2708,2736,
+2764,2792,2820,2849,2877,2906,2934,2963,2992,3021,3050,3079,
+3109,3138,3168,3198,3228,3258,3288,3318,3348,3379,3410,3440,
+3471,3502,3533,3564,3596,3627,3659,3691,3722,3754,3787,3819,
+3851,3883,3916,3949,3981,4014,4047,4081,4114,4147,4181,4214,
+4248,4282,4316,4350,4384,4418,4453,4487,4522,4556,4591,4626,
+4661,4696,4732,4767,4804,4839,4875,4911,4947,4983,5019,5055,
+5092,5128,5165,5201,5238,5275,5312,5349,5386,5424,5461,5499,
+5536,5574,5612,5650,5688,5726,5764,5802,5841,5879,5918,5957,
+5995,6034,6073,6113,6152,6191,6230,6270,6309,6349,6389,6429,
+6469,6509,6549,6589,6630,6670,6711,6751,6792,6833,6874,6915,
+6956,6997,7038,7079,7121,7162,7204,7246,7289,7330,7372,7414,
+7456,7499,7541,7583,7626,7668,7711,7754,7796,7839,7882,7925,
+7968,8011,8055,8098,8141,8185,8228,8272,8316,8359,8403,8447,
+8491,8535,8580,8624,8668,8712,8757,8801,8846,8891,8935,8980,
+9025,9070,9115,9160,9205,9250,9296,9341,9387,9432,9478,9523,
+9569,9615,9660,9706,9752,9798,9844,9890,9937,9983,10029,10075,
+10123,10170,10216,10263,10310,10356,10403,10450,10497,10544,10591,10638,
+10685,10732,10779,10826,10874,10921,10969,11016,11064,11111,11159,11206,
+11254,11302,11350,11398,11445,11493,11541,11589,11637,11686,11734,11782,
+11830,11879,11927,11975,12024,12072,12121,12169,12218,12267,12315,12364,
+12413,12461,12510,12559,12608,12657,12706,12755,12804,12853,12902,12951,
+13000,13050,13099,13148,13199,13248,13298,13347,13396,13446,13495,13545,
+13594,13644,13693,13743,13793,13842,13892,13942,13991,14041,14091,14141,
+14190,14240,14290,14340,14390,14440,14490,14540,14590,14640,14690,14740,
+14790,14840,14890,14940,14990,15040,15090,15140,15190,15240,15290,15341,
+15391,15441,15491,15541,15592,15642,15692,15742,15792,15843,15893,15943,
+15993,16044,16094,16144,16194,16245,16295,16345,16397,16447,16498,16548,
+16598,16648,16699,16749,16799,16849,16900,16950,17000,17050,17101,17151,
+17201,17251,17301,17352,17402,17452,17502,17552,17602,17652,17703,17753,
+17803,17853,17903,17953,18003,18053,18103,18153,18203,18253,18303,18353,
+18403,18452,18502,18552,18602,18652,18701,18751,18801,18851,18900,18950,
+19000,19049,19099,19148,19198,19247,19297,19346,19396,19445,19495,19544,
+19595,19644,19693,19742,19792,19841,19890,19939,19988,20037,20086,20135,
+20184,20233,20282,20330,20379,20428,20477,20525,20574,20622,20671,20719,
+20768,20816,20865,20913,20961,21010,21058,21106,21154,21202,21250,21298,
+21346,21394,21442,21490,21537,21585,21633,21680,21728,21775,21823,21870,
+21917,21965,22012,22059,22106,22153,22200,22247,22294,22341,22388,22435,
+22481,22528,22574,22621,22669,22715,22762,22808,22854,22900,22946,22992,
+23038,23084,23130,23176,23222,23267,23313,23358,23404,23449,23494,23540,
+23585,23630,23675,23720,23765,23810,23855,23899,23944,23988,24033,24077,
+24122,24166,24210,24254,24298,24342,24386,24430,24474,24517,24561,24605,
+24648,24691,24735,24778,24821,24864,24907,24950,24993,25035,25078,25121,
+25163,25206,25248,25290,25332,25374,25416,25458,25501,25543,25585,25626,
+25668,25709,25750,25792,25833,25874,25915,25955,25996,26037,26077,26118,
+26158,26199,26239,26279,26319,26359,26399,26438,26478,26518,26557,26596,
+26636,26675,26714,26753,26792,26831,26869,26908,26946,26985,27023,27061,
+27099,27137,27175,27213,27250,27288,27325,27363,27400,27437,27474,27511,
+27548,27585,27621,27658,27694,27731,27767,27803,27839,27875,27911,27946,
+27983,28019,28054,28089,28124,28159,28194,28229,28264,28298,28333,28367,
+28401,28435,28469,28503,28537,28571,28604,28638,28671,28704,28737,28770,
+28803,28836,28868,28901,28933,28965,28998,29030,29061,29093,29125,29156,
+29188,29219,29250,29281,29312,29343,29374,29404,29435,29465,29495,29526,
+29555,29585,29615,29645,29674,29703,29733,29762,29791,29819,29848,29877,
+29905,29934,29962,29990,30019,30046,30074,30102,30129,30156,30184,30211,
+30237,30264,30291,30317,30344,30370,30396,30422,30448,30474,30499,30525,
+30550,30575,30600,30625,30650,30675,30699,30724,30748,30772,30796,30820,
+30844,30867,30891,30914,30937,30960,30983,31006,31028,31051,31073,31095,
+31117,31139,31161,31183,31204,31226,31247,31268,31289,31310,31330,31351,
+31371,31391,31412,31431,31451,31471,31491,31510,31530,31549,31568,31587,
+31605,31624,31642,31660,31679,31697,31714,31732,31750,31767,31784,31801,
+31818,31835,31852,31868,31884,31901,31917,31933,31948,31964,31980,31995,
+32010,32025,32040,32055,32069,32084,32098,32112,32126,32140,32154,32167,
+32181,32194,32207,32220,32233,32246,32258,32271,32283,32295,32307,32319,
+32330,32342,32353,32364,32375,32386,32397,32407,32418,32428,32438,32448,
+32458,32468,32477,32487,32496,32505,32514,32523,32531,32540,32548,32556,
+32564,32572,32580,32587,32595,32602,32609,32616,32623,32629,32636,32642,
+32648,32654,32660,32666,32671,32677,32682,32687,32692,32697,32701,32706,
+32710,32714,32718,32722,32726,32729,32733,32736,32739,32742,32745,32747,
+32750,32752,32754,32756,32758,32760,32761,32763,32764,32765,32766,32767,
+32768,32768,32768,32768,32768,32768,32768,32768,32767,32766,32765,32764,
+32763,32762,32760,32758,32756,32754,32752,32750,32748,32745,32742,32739,
+32736,32733,32729,32726,32722,32718,32714,32710,32706,32701,32697,32692,
+32687,32682,32677,32671,32666,32660,32654,32648,32642,32636,32629,32623,
+32616,32609,32602,32595,32587,32580,32572,32564,32556,32548,32540,32532,
+32523,32514,32505,32496,32487,32478,32468,32459,32448,32438,32428,32418,
+32408,32397,32386,32376,32365,32353,32342,32331,32319,32307,32295,32283,
+32271,32259,32246,32233,32221,32208,32195,32181,32168,32154,32141,32127,
+32113,32099,32084,32070,32055,32040,32026,32011,31995,31980,31965,31949,
+31933,31917,31901,31885,31869,31852,31835,31819,31802,31785,31767,31750,
+31733,31715,31697,31679,31661,31643,31624,31606,31587,31568,31549,31530,
+31510,31491,31472,31452,31432,31412,31392,31372,31351,31331,31310,31289,
+31269,31247,31226,31205,31183,31162,31140,31118,31096,31074,31051,31029,
+31006,30984,30961,30938,30915,30891,30868,30844,30821,30797,30773,30749,
+30724,30700,30675,30651,30626,30601,30576,30551,30526,30500,30475,30449,
+30423,30397,30371,30345,30318,30292,30265,30238,30211,30184,30157,30130,
+30103,30075,30047,30020,29991,29963,29934,29906,29878,29849,29820,29792,
+29763,29734,29704,29675,29646,29616,29586,29556,29526,29496,29466,29436,
+29405,29375,29344,29313,29282,29251,29220,29189,29157,29126,29094,29062,
+29031,28999,28966,28934,28902,28869,28837,28804,28771,28738,28705,28672,
+28639,28605,28572,28538,28504,28470,28436,28402,28368,28334,28299,28265,
+28230,28195,28160,28125,28090,28055,28020,27984,27948,27912,27876,27840,
+27804,27768,27732,27696,27659,27623,27586,27549,27512,27475,27438,27401,
+27364,27327,27289,27252,27214,27176,27138,27100,27062,27024,26986,26947,
+26909,26870,26832,26793,26754,26715,26676,26637,26598,26558,26519,26479,
+26440,26400,26360,26320,26280,26240,26200,26160,26119,26079,26038,25997,
+25957,25916,25875,25834,25793,25752,25710,25669,25628,25586,25544,25503,
+25460,25418,25376,25334,25291,25249,25207,25164,25122,25079,25037,24994,
+24951,24908,24865,24822,24779,24736,24693,24649,24606,24562,24519,24475,
+24431,24388,24344,24300,24256,24212,24167,24123,24079,24034,23990,23945,
+23901,23856,23811,23766,23721,23676,23631,23586,23541,23496,23451,23405,
+23360,23314,23269,23223,23177,23132,23086,23040,22994,22948,22902,22856,
+22809,22763,22717,22670,22622,22576,22529,22483,22436,22389,22343,22296,
+22249,22202,22155,22108,22061,22013,21966,21919,21872,21824,21777,21729,
+21682,21634,21586,21539,21491,21443,21395,21348,21300,21252,21204,21156,
+21107,21059,21011,20963,20915,20866,20818,20769,20721,20673,20624,20575,
+20527,20478,20429,20381,20332,20283,20234,20185,20137,20088,20039,19990,
+19941,19891,19842,19793,19744,19695,19646,19596,19545,19496,19447,19397,
+19348,19298,19249,19199,19150,19100,19051,19001,18952,18902,18852,18803,
+18753,18703,18653,18603,18554,18504,18454,18404,18354,18304,18254,18204,
+18154,18104,18054,18004,17954,17904,17854,17804,17754,17704,17654,17604,
+17554,17504,17453,17403,17353,17303,17253,17203,17152,17102,17052,17002,
+16951,16901,16851,16801,16750,16700,16650,16600,16549,16499,16449,16399,
+16347,16297,16246,16196,16146,16095,16045,15995,15945,15894,15844,15794,
+15744,15694,15643,15593,15543,15493,15443,15392,15342,15292,15242,15192,
+15142,15092,15041,14991,14941,14891,14841,14791,14741,14691,14641,14591,
+14541,14491,14441,14391,14342,14292,14242,14192,14142,14092,14043,13993,
+13943,13893,13844,13794,13745,13695,13645,13596,13546,13497,13447,13398,
+13349,13299,13250,13200,13150,13100,13051,13002,12953,12904,12855,12805,
+12756,12707,12658,12610,12561,12512,12463,12414,12365,12317,12268,12219,
+12171,12122,12074,12025,11977,11928,11880,11832,11784,11735,11687,11639,
+11591,11543,11495,11447,11399,11351,11303,11256,11208,11160,11113,11065,
+11017,10970,10923,10875,10828,10781,10733,10686,10639,10592,10545,10498,
+10451,10405,10358,10311,10264,10218,10171,10125,10077,10031,9984,9938,
+9892,9846,9800,9754,9708,9662,9616,9570,9525,9479,9433,9388,
+9343,9297,9252,9207,9162,9116,9071,9026,8982,8937,8892,8847,
+8803,8758,8714,8669,8625,8581,8537,8493,8449,8405,8361,8317,
+8273,8230,8186,8143,8099,8056,8013,7970,7926,7883,7840,7798,
+7755,7712,7670,7627,7585,7542,7500,7458,7416,7374,7332,7290,
+7247,7205,7164,7122,7081,7039,6998,6957,6916,6875,6834,6793,
+6752,6712,6671,6631,6591,6550,6510,6470,6430,6390,6350,6311,
+6271,6232,6192,6153,6114,6075,6036,5997,5958,5919,5881,5842,
+5804,5765,5727,5689,5651,5613,5575,5537,5500,5462,5425,5387,
+5350,5313,5276,5239,5202,5166,5129,5093,5056,5020,4984,4948,
+4912,4876,4840,4805,4768,4733,4698,4662,4627,4592,4557,4523,
+4488,4454,4419,4385,4351,4317,4283,4249,4215,4182,4148,4115,
+4082,4048,4015,3982,3950,3917,3884,3852,3820,3788,3755,3723,
+3692,3660,3628,3597,3565,3534,3503,3472,3441,3410,3380,3349,
+3319,3289,3259,3228,3199,3169,3139,3110,3080,3051,3022,2993,
+2964,2935,2907,2878,2850,2821,2793,2765,2736,2709,2681,2654,
+2626,2599,2572,2545,2518,2491,2465,2438,2412,2386,2360,2334,
+2308,2282,2257,2232,2206,2181,2156,2131,2107,2082,2058,2033,
+2009,1985,1961,1937,1914,1890,1867,1844,1820,1798,1775,1752,
+1729,1707,1685,1663,1641,1619,1597,1576,1554,1533,1512,1491,
+1470,1449,1428,1408,1388,1368,1347,1328,1308,1288,1269,1249,
+1230,1211,1192,1173,1154,1136,1118,1099,1081,1064,1046,1028,
+1011,993,976,959,942,926,909,893,876,860,844,828,
+813,797,782,766,751,736,722,707,692,678,664,650,
+636,622,608,595,581,568,555,542,530,517,505,492,
+480,468,456,445,433,422,410,399,388,378,367,356,
+346,336,326,316,306,296,287,278,268,259,251,242,
+233,225,217,209,201,193,186,178,171,164,157,150,
+143,137,130,124,118,112,106,101,95,90,85,80,
+75,70,65,61,57,53,49,45,41,38,35,31,
+28,26,23,20,18,16,14,12,10,8,7,5,
+4,3,2,2,1,1,1,1};
+const int32_t hann_1024 [] = {1,1,2,3,5,8,12,16,20,25,31,38,
+45,53,61,70,80,90,101,112,124,137,150,164,
+178,193,209,225,242,259,278,296,316,336,356,378,
+399,422,445,468,492,517,542,568,595,622,650,678,
+707,737,767,798,829,861,893,926,960,994,1029,1064,
+1100,1137,1174,1211,1250,1289,1328,1368,1409,1450,1491,1533,
+1576,1620,1663,1708,1753,1798,1844,1891,1939,1987,2035,2084,
+2133,2183,2233,2284,2336,2388,2440,2493,2547,2601,2655,2710,
+2767,2823,2880,2937,2995,3053,3111,3171,3230,3291,3351,3412,
+3474,3536,3599,3662,3726,3791,3855,3920,3986,4052,4118,4185,
+4252,4320,4388,4457,4526,4596,4666,4736,4808,4880,4951,5024,
+5096,5169,5243,5317,5391,5466,5541,5616,5692,5769,5846,5923,
+6002,6079,6158,6237,6316,6395,6475,6555,6636,6717,6798,6880,
+6962,7044,7127,7210,7295,7379,7463,7548,7632,7718,7803,7889,
+7975,8061,8148,8235,8323,8410,8498,8586,8676,8765,8854,8944,
+9034,9123,9214,9304,9395,9486,9577,9669,9761,9853,9945,10038,
+10132,10225,10318,10412,10506,10600,10694,10788,10883,10977,11072,11168,
+11263,11359,11454,11550,11648,11744,11841,11938,12034,12131,12229,12326,
+12423,12521,12619,12717,12815,12913,13011,13110,13210,13308,13407,13506,
+13605,13704,13803,13903,14002,14102,14201,14301,14401,14501,14600,14700,
+14802,14902,15002,15102,15203,15303,15403,15504,15604,15705,15805,15905,
+16006,16106,16207,16308,16410,16510,16611,16711,16812,16912,17013,17113,
+17214,17314,17414,17515,17615,17715,17815,17915,18017,18117,18217,18317,
+18417,18516,18616,18715,18815,18914,19014,19113,19212,19311,19410,19508,
+19609,19707,19805,19904,20002,20100,20198,20295,20393,20490,20588,20685,
+20782,20878,20975,21071,21169,21265,21361,21457,21552,21647,21743,21837,
+21932,22027,22121,22215,22309,22402,22496,22589,22683,22776,22869,22961,
+23053,23144,23236,23327,23418,23509,23599,23689,23779,23869,23958,24047,
+24137,24225,24313,24401,24489,24576,24663,24750,24836,24922,25007,25093,
+25178,25262,25347,25431,25516,25599,25682,25765,25847,25929,26010,26091,
+26172,26253,26333,26412,26492,26571,26649,26727,26806,26884,26961,27037,
+27113,27189,27265,27340,27414,27488,27562,27635,27708,27781,27853,27924,
+27996,28067,28137,28207,28277,28345,28414,28482,28550,28617,28683,28749,
+28815,28880,28945,29010,29074,29138,29201,29263,29325,29386,29447,29508,
+29568,29627,29686,29744,29802,29860,29917,29973,30030,30085,30140,30195,
+30248,30302,30354,30407,30458,30510,30560,30610,30660,30709,30758,30806,
+30854,30901,30947,30993,31038,31083,31127,31171,31214,31256,31298,31339,
+31380,31420,31460,31499,31538,31576,31613,31650,31686,31722,31757,31792,
+31826,31859,31892,31924,31955,31986,32017,32047,32076,32105,32133,32160,
+32187,32213,32239,32264,32288,32312,32336,32358,32380,32402,32423,32443,
+32463,32482,32500,32518,32535,32552,32568,32583,32598,32612,32626,32639,
+32651,32663,32674,32684,32694,32704,32712,32720,32728,32734,32741,32746,
+32751,32755,32759,32762,32765,32767,32768,32768,32768,32768,32767,32765,
+32762,32759,32755,32751,32746,32741,32735,32728,32720,32712,32704,32694,
+32684,32674,32663,32651,32639,32626,32612,32598,32583,32568,32552,32536,
+32518,32501,32482,32463,32443,32423,32402,32381,32359,32336,32313,32289,
+32264,32239,32214,32188,32161,32133,32105,32077,32047,32017,31987,31956,
+31924,31892,31859,31826,31792,31758,31723,31687,31651,31614,31577,31539,
+31500,31461,31421,31381,31340,31299,31257,31214,31171,31128,31083,31039,
+30994,30948,30901,30855,30806,30758,30710,30661,30611,30561,30510,30459,
+30408,30355,30303,30249,30195,30141,30086,30031,29974,29918,29861,29803,
+29745,29687,29628,29569,29509,29448,29387,29326,29264,29202,29139,29075,
+29011,28946,28881,28816,28751,28684,28618,28551,28483,28415,28347,28278,
+28208,28138,28068,27997,27925,27854,27782,27709,27636,27563,27489,27415,
+27341,27266,27190,27115,27038,26962,26885,26808,26729,26650,26572,26493,
+26414,26334,26254,26173,26093,26011,25930,25848,25766,25683,25600,25517,
+25432,25348,25264,25179,25094,25009,24923,24837,24751,24664,24577,24490,
+24403,24315,24227,24138,24048,23959,23870,23780,23691,23600,23510,23419,
+23328,23237,23146,23054,22962,22870,22778,22685,22590,22497,22404,22310,
+22216,22122,22028,21934,21839,21744,21649,21554,21458,21363,21267,21171,
+21073,20976,20880,20783,20686,20589,20492,20394,20297,20199,20101,20003,
+19905,19807,19709,19610,19510,19411,19312,19213,19114,19015,18916,18816,
+18717,18617,18518,18418,18318,18218,18119,18019,17917,17817,17717,17616,
+17516,17416,17315,17215,17115,17014,16914,16813,16713,16612,16512,16411,
+16309,16209,16108,16008,15907,15807,15706,15606,15505,15405,15305,15204,
+15104,15004,14904,14804,14702,14602,14502,14402,14303,14203,14103,14004,
+13904,13805,13706,13607,13508,13409,13310,13211,13111,13013,12914,12816,
+12718,12620,12522,12425,12327,12230,12133,12036,11939,11842,11746,11650,
+11552,11456,11360,11265,11169,11074,10979,10884,10790,10695,10601,10507,
+10413,10320,10227,10133,10039,9947,9854,9762,9670,9579,9488,9396,
+9306,9215,9125,9035,8945,8856,8767,8678,8588,8500,8412,8324,
+8237,8149,8063,7976,7890,7804,7719,7634,7549,7464,7380,7296,
+7212,7129,7046,6963,6881,6800,6718,6637,6557,6476,6396,6317,
+6238,6159,6081,6003,5924,5847,5770,5694,5618,5542,5467,5392,
+5318,5244,5170,5097,5025,4952,4881,4809,4737,4667,4597,4527,
+4458,4389,4321,4253,4186,4119,4053,3987,3921,3856,3792,3727,
+3663,3600,3537,3475,3413,3352,3291,3231,3172,3112,3054,2996,
+2938,2881,2824,2768,2711,2656,2602,2547,2494,2441,2388,2336,
+2285,2234,2184,2134,2084,2036,1987,1940,1892,1845,1799,1753,
+1708,1664,1620,1577,1534,1492,1450,1409,1369,1329,1289,1251,
+1212,1174,1137,1101,1065,1029,995,960,927,894,861,829,
+798,767,737,708,678,650,622,595,569,543,517,493,
+468,445,422,400,378,357,336,316,297,278,260,242,
+225,209,193,178,164,150,137,124,112,101,90,80,
+70,61,53,45,38,31,26,20,16,12,8,5,
+3,2,1,1};
+const int32_t hann_512 [] = {1,2,5,12,20,31,45,61,80,101,124,150,
+179,209,243,278,317,357,400,445,493,544,596,651,
+709,768,830,895,962,1031,1102,1176,1252,1331,1411,1494,
+1580,1667,1756,1848,1943,2039,2137,2237,2340,2445,2552,2660,
+2772,2885,3000,3117,3237,3358,3481,3606,3733,3862,3993,4125,
+4261,4397,4535,4674,4817,4960,5105,5252,5401,5551,5703,5856,
+6012,6169,6327,6486,6649,6811,6975,7140,7308,7476,7646,7816,
+7990,8163,8338,8513,8692,8870,9049,9229,9412,9595,9778,9963,
+10149,10336,10523,10711,10902,11092,11282,11474,11668,11860,12054,12248,
+12445,12640,12836,13033,13231,13429,13627,13825,14026,14225,14424,14624,
+14825,15026,15226,15427,15629,15830,16031,16232,16435,16636,16837,17038,
+17240,17441,17641,17842,18044,18243,18443,18642,18843,19041,19240,19437,
+19636,19833,20029,20225,20422,20616,20810,21004,21198,21389,21581,21771,
+21962,22150,22338,22525,22712,22897,23081,23264,23448,23629,23808,23987,
+24166,24342,24517,24691,24865,25037,25207,25376,25544,25710,25875,26038,
+26201,26361,26520,26677,26834,26988,27141,27292,27442,27589,27735,27879,
+28023,28164,28302,28439,28576,28709,28841,28970,29099,29225,29349,29471,
+29592,29710,29826,29940,30053,30162,30270,30376,30480,30582,30681,30778,
+30874,30966,31057,31145,31232,31316,31398,31477,31555,31630,31702,31772,
+31841,31906,31969,32030,32089,32145,32199,32250,32300,32346,32390,32432,
+32472,32509,32543,32575,32605,32632,32657,32679,32699,32716,32731,32743,
+32753,32761,32766,32768,32768,32766,32761,32753,32743,32731,32716,32699,
+32679,32657,32632,32605,32575,32543,32509,32472,32433,32391,32347,32300,
+32251,32199,32146,32090,32031,31970,31907,31841,31773,31703,31630,31555,
+31478,31398,31317,31233,31146,31058,30967,30874,30779,30682,30582,30481,
+30377,30271,30163,30053,29941,29827,29711,29593,29472,29350,29226,29100,
+28971,28842,28710,28577,28441,28304,28165,28024,27881,27736,27591,27443,
+27293,27142,26989,26835,26679,26521,26363,26202,26039,25876,25712,25546,
+25377,25208,25038,24867,24693,24519,24344,24167,23988,23810,23630,23449,
+23266,23083,22899,22714,22526,22340,22152,21963,21772,21582,21391,21199,
+21005,20812,20618,20423,20227,20031,19835,19638,19439,19241,19043,18844,
+18644,18445,18245,18045,17843,17643,17442,17242,17039,16838,16637,16436,
+16234,16033,15832,15631,15428,15228,15027,14827,14625,14426,14226,14027,
+13827,13628,13430,13233,13034,12838,12642,12446,12250,12056,11862,11669,
+11475,11284,11093,10903,10713,10525,10337,10151,9964,9780,9596,9414,
+9231,9050,8871,8693,8515,8339,8164,7991,7818,7647,7478,7309,
+7141,6976,6812,6650,6488,6328,6170,6014,5858,5704,5553,5403,
+5253,5106,4961,4818,4676,4536,4398,4262,4126,3994,3863,3734,
+3607,3482,3359,3238,3118,3001,2886,2773,2661,2553,2446,2341,
+2238,2138,2039,1943,1849,1757,1668,1580,1495,1412,1331,1253,
+1177,1103,1032,962,895,831,769,709,651,597,544,494,
+446,400,357,317,278,243,210,179,150,124,101,80,
+61,45,32,20,12,5,2,1};
diff --git a/apps/plugins/fft/fft.c b/apps/plugins/fft/fft.c
new file mode 100644
index 0000000000..531c9af4cb
--- /dev/null
+++ b/apps/plugins/fft/fft.c
@@ -0,0 +1,1165 @@
+/***************************************************************************
+* __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Delyan Kratunov
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+
+#include "lib/helper.h"
+#include "lib/xlcd.h"
+#include "math.h"
+#include "thread.h"
+
+#ifndef HAVE_LCD_COLOR
+#include "lib/grey.h"
+#endif
+
+PLUGIN_HEADER
+
+#ifndef HAVE_LCD_COLOR
+GREY_INFO_STRUCT
+#endif
+
+#if CONFIG_KEYPAD == ARCHOS_AV300_PAD
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_F3
+# define FFT_WINDOW BUTTON_F1
+# define FFT_SCALE BUTTON_UP
+# define FFT_QUIT BUTTON_OFF
+
+#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
+ (CONFIG_KEYPAD == IRIVER_H300_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_REC
+# define FFT_WINDOW BUTTON_SELECT
+# define FFT_SCALE BUTTON_UP
+# define FFT_QUIT BUTTON_OFF
+
+#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
+ (CONFIG_KEYPAD == IPOD_3G_PAD) || \
+ (CONFIG_KEYPAD == IPOD_1G2G_PAD)
+# define MINESWP_SCROLLWHEEL
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION (BUTTON_SELECT | BUTTON_LEFT)
+# define FFT_WINDOW (BUTTON_SELECT | BUTTON_RIGHT)
+# define FFT_SCALE BUTTON_MENU
+# define FFT_QUIT (BUTTON_SELECT | BUTTON_MENU)
+
+#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_SELECT
+# define FFT_WINDOW BUTTON_PLAY
+# define FFT_SCALE BUTTON_UP
+# define FFT_QUIT BUTTON_POWER
+
+#elif (CONFIG_KEYPAD == GIGABEAT_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_SCALE BUTTON_UP
+# define FFT_ORIENTATION BUTTON_SELECT
+# define FFT_WINDOW BUTTON_A
+# define FFT_QUIT BUTTON_POWER
+
+#elif (CONFIG_KEYPAD == SANSA_E200_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_SELECT
+# define FFT_WINDOW BUTTON_REC
+# define FFT_SCALE BUTTON_UP
+# define FFT_QUIT BUTTON_POWER
+
+#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION (BUTTON_SELECT | BUTTON_LEFT)
+# define FFT_WINDOW (BUTTON_SELECT | BUTTON_RIGHT)
+# define FFT_SCALE BUTTON_UP
+# define FFT_QUIT BUTTON_POWER
+
+#elif (CONFIG_KEYPAD == SANSA_C200_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_UP
+# define FFT_WINDOW BUTTON_REC
+# define FFT_SCALE BUTTON_SELECT
+# define FFT_QUIT BUTTON_POWER
+#elif (CONFIG_KEYPAD == SANSA_M200_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_UP
+# define FFT_WINDOW BUTTON_DOWN
+# define FFT_SCALE BUTTON_SELECT
+# define FFT_QUIT BUTTON_POWER
+#elif (CONFIG_KEYPAD == SANSA_CLIP_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_UP
+# define FFT_WINDOW BUTTON_HOME
+# define FFT_SCALE BUTTON_SELECT
+# define FFT_QUIT BUTTON_POWER
+
+#elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_FF
+# define FFT_WINDOW BUTTON_SCROLL_UP
+# define FFT_SCALE BUTTON_REW
+# define FFT_QUIT BUTTON_POWER
+
+#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_MENU
+# define FFT_WINDOW BUTTON_PREV
+# define FFT_SCALE BUTTON_UP
+# define FFT_QUIT BUTTON_BACK
+
+#elif (CONFIG_KEYPAD == MROBE100_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_PLAY
+# define FFT_WINDOW BUTTON_SELECT
+# define FFT_SCALE BUTTON_UP
+# define FFT_QUIT BUTTON_POWER
+
+#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
+# define FFT_PREV_GRAPH BUTTON_RC_REW
+# define FFT_NEXT_GRAPH BUTTON_RC_FF
+# define FFT_ORIENTATION BUTTON_RC_MODE
+# define FFT_WINDOW BUTTON_RC_PLAY
+# define FFT_SCALE BUTTON_RC_VOL_UP
+# define FFT_QUIT BUTTON_RC_REC
+
+#elif (CONFIG_KEYPAD == COWON_D2_PAD)
+# define FFT_QUIT BUTTON_POWER
+# define FFT_PREV_GRAPH BUTTON_PLUS
+# define FFT_NEXT_GRAPH BUTTON_MINUS
+
+#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_MENU
+# define FFT_WINDOW BUTTON_SELECT
+# define FFT_SCALE BUTTON_UP
+# define FFT_QUIT BUTTON_BACK
+
+#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_SELECT
+# define FFT_WINDOW BUTTON_MENU
+# define FFT_SCALE BUTTON_UP
+# define FFT_QUIT BUTTON_POWER
+
+#elif (CONFIG_KEYPAD == SAMSUNG_YH_PAD)
+# define FFT_PREV_GRAPH BUTTON_LEFT
+# define FFT_NEXT_GRAPH BUTTON_RIGHT
+# define FFT_ORIENTATION BUTTON_UP
+# define FFT_WINDOW BUTTON_DOWN
+# define FFT_SCALE BUTTON_FFWD
+# define FFT_QUIT BUTTON_PLAY
+
+#else
+#error No keymap defined!
+#endif
+
+#ifdef HAVE_LCD_COLOR
+#include "pluginbitmaps/fft_colors.h"
+#endif
+
+#include "kiss_fftr.h"
+#include "_kiss_fft_guts.h" /* sizeof(struct kiss_fft_state) */
+#include "const.h"
+
+#define FFT_SIZE 2048
+#define ARRAYSIZE_IN (FFT_SIZE)
+#define ARRAYSIZE_OUT (FFT_SIZE/2)
+#define ARRAYSIZE_PLOT (FFT_SIZE/4)
+#define BUFSIZE_FFT (sizeof(struct kiss_fft_state)+sizeof(kiss_fft_cpx)*(FFT_SIZE-1))
+#define BUFSIZE_FFTR (BUFSIZE_FFT+sizeof(struct kiss_fftr_state)+sizeof(kiss_fft_cpx)*(FFT_SIZE*3/2))
+#define BUFSIZE BUFSIZE_FFTR
+#define FFT_ALLOC kiss_fftr_alloc
+#define FFT_FFT kiss_fftr
+#define FFT_CFG kiss_fftr_cfg
+
+#define __COEFF(type,size) type##_##size
+#define _COEFF(x, y) __COEFF(x,y) /* force the preprocessor to evaluate FFT_SIZE) */
+#define HANN_COEFF _COEFF(hann, FFT_SIZE)
+#define HAMMING_COEFF _COEFF(hamming, FFT_SIZE)
+
+/****************************** Globals ****************************/
+
+static kiss_fft_scalar input[ARRAYSIZE_IN];
+static kiss_fft_cpx output[ARRAYSIZE_OUT];
+static int32_t plot[ARRAYSIZE_PLOT];
+static char buffer[BUFSIZE];
+
+#if LCD_DEPTH > 1 /* greyscale or color, enable spectrogram */
+#define MODES_COUNT 3
+#else
+#define MODES_COUNT 2
+#endif
+
+const unsigned char* modes_text[] = { "Lines", "Bars", "Spectrogram" };
+const unsigned char* scales_text[] = { "Linear scale", "Logarithmic scale" };
+const unsigned char* window_text[] = { "Hamming window", "Hann window" };
+
+struct mutex input_mutex;
+bool input_thread_run = true;
+bool input_thread_has_data = false;
+
+struct {
+ int32_t mode;
+ bool logarithmic;
+ bool orientation_vertical;
+ int window_func;
+ struct {
+ int column;
+ int row;
+ } spectrogram;
+ struct {
+ bool orientation;
+ bool mode;
+ bool scale;
+ } changed;
+} graph_settings;
+
+#define COLORS BMPWIDTH_fft_colors
+
+/************************* End of globals *************************/
+
+/************************* Math functions *************************/
+#define QLOG_MAX 286286
+#define QLIN_MAX 1534588906
+#define QLN_10 float_q16(2.302585093)
+#define LIN_MAX (QLIN_MAX >> 16)
+
+/* Returns logarithmically scaled values in S15.16 format */
+inline int32_t get_log_value(int32_t value)
+{
+ return Q16_DIV(fp16_log(value), QLN_10);
+}
+
+/* Apply window function to input
+ * 0 - Hamming window
+ * 1 - Hann window */
+#define WINDOW_COUNT 2
+void apply_window_func(char mode)
+{
+ switch(mode)
+ {
+ case 0: /* Hamming window */
+ {
+ size_t i;
+ for (i = 0; i < ARRAYSIZE_IN; ++i)
+ {
+ input[i] = Q15_MUL(input[i] << 15, HAMMING_COEFF[i]) >> 15;
+ }
+ break;
+ }
+ case 1: /* Hann window */
+ {
+ size_t i;
+ for (i = 0; i < ARRAYSIZE_IN; ++i)
+ {
+ input[i] = Q15_MUL(input[i] << 15, HANN_COEFF[i]) >> 15;
+ }
+ break;
+ }
+ }
+}
+
+/* Calculates the magnitudes from complex numbers and returns the maximum */
+int32_t calc_magnitudes(bool logarithmic)
+{
+ int64_t tmp;
+ size_t i;
+
+ int32_t max = -2147483647;
+
+ /* Calculate the magnitude, discarding the phase.
+ * The sum of the squares can easily overflow the 15-bit (s15.16)
+ * requirement for fsqrt, so we scale the data down */
+ for (i = 0; i < ARRAYSIZE_PLOT; ++i)
+ {
+ tmp = output[i].r * output[i].r + output[i].i * output[i].i;
+ tmp <<= 16;
+
+ tmp = fsqrt64(tmp, 16);
+
+ if (logarithmic)
+ tmp = get_log_value(tmp & 0x7FFFFFFF);
+
+ plot[i] = tmp;
+
+ if (plot[i] > max)
+ max = plot[i];
+ }
+ return max;
+}
+/************************ End of math functions ***********************/
+
+/********************* Plotting functions (modes) *********************/
+void draw_lines_vertical(void);
+void draw_lines_horizontal(void);
+void draw_bars_vertical(void);
+void draw_bars_horizontal(void);
+void draw_spectrogram_vertical(void);
+void draw_spectrogram_horizontal(void);
+
+void draw(const unsigned char* message)
+{
+ static uint32_t show_message = 0;
+ static unsigned char* last_message = 0;
+
+ static char last_mode = 0;
+ static bool last_orientation = true, last_scale = true;
+
+ if (message != 0)
+ {
+ last_message = (unsigned char*) message;
+ show_message = 5;
+ }
+
+ if(last_mode != graph_settings.mode)
+ {
+ last_mode = graph_settings.mode;
+ graph_settings.changed.mode = true;
+ }
+ if(last_scale != graph_settings.logarithmic)
+ {
+ last_scale = graph_settings.logarithmic;
+ graph_settings.changed.scale = true;
+ }
+ if(last_orientation != graph_settings.orientation_vertical)
+ {
+ last_orientation = graph_settings.orientation_vertical;
+ graph_settings.changed.orientation = true;
+ }
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_set_foreground(LCD_DEFAULT_FG);
+ rb->lcd_set_background(LCD_DEFAULT_BG);
+#else
+ grey_set_foreground(GREY_BLACK);
+ grey_set_background(GREY_WHITE);
+#endif
+
+ switch (graph_settings.mode)
+ {
+ default:
+ case 0: {
+
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_clear_display();
+#else
+ grey_clear_display();
+#endif
+
+ if (graph_settings.orientation_vertical)
+ draw_lines_vertical();
+ else
+ draw_lines_horizontal();
+ break;
+ }
+ case 1: {
+
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_clear_display();
+#else
+ grey_clear_display();
+#endif
+
+ if(graph_settings.orientation_vertical)
+ draw_bars_vertical();
+ else
+ draw_bars_horizontal();
+
+ break;
+ }
+ case 2: {
+ if(graph_settings.orientation_vertical)
+ draw_spectrogram_vertical();
+ else
+ draw_spectrogram_horizontal();
+ break;
+ }
+ }
+
+ if (show_message > 0)
+ {
+ /* We have a message to show */
+
+ int x, y;
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_getstringsize(last_message, &x, &y);
+#else
+ grey_getstringsize(last_message, &x, &y);
+#endif
+ /* x and y give the size of the box for the popup */
+ x += 6; /* 3 px of horizontal padding and */
+ y += 4; /* 2 px of vertical padding */
+
+ /* In vertical spectrogram mode, leave space for the popup
+ * before actually drawing it (if space is needed) */
+ if(graph_settings.mode == 2 &&
+ graph_settings.orientation_vertical &&
+ graph_settings.spectrogram.column > LCD_WIDTH-x-2)
+ {
+#ifdef HAVE_LCD_COLOR
+ xlcd_scroll_left(graph_settings.spectrogram.column -
+ (LCD_WIDTH - x - 1));
+#else
+ grey_scroll_left(graph_settings.spectrogram.column -
+ (LCD_WIDTH - x - 1));
+#endif
+ graph_settings.spectrogram.column = LCD_WIDTH - x - 2;
+ }
+
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_set_foreground(LCD_DARKGRAY);
+ rb->lcd_fillrect(LCD_WIDTH-1-x, 0, LCD_WIDTH-1, y);
+
+ rb->lcd_set_foreground(LCD_DEFAULT_FG);
+ rb->lcd_set_background(LCD_DARKGRAY);
+ rb->lcd_putsxy(LCD_WIDTH-1-x+3, 2, last_message);
+ rb->lcd_set_background(LCD_DEFAULT_BG);
+#else
+ grey_set_foreground(GREY_LIGHTGRAY);
+ grey_fillrect(LCD_WIDTH-1-x, 0, LCD_WIDTH-1, y);
+
+ grey_set_foreground(GREY_BLACK);
+ grey_set_background(GREY_LIGHTGRAY);
+ grey_putsxy(LCD_WIDTH-1-x+3, 2, last_message);
+ grey_set_background(GREY_WHITE);
+#endif
+
+ show_message--;
+ }
+ else if(last_message != 0)
+ {
+ if(graph_settings.mode != 2)
+ {
+ /* These modes clear the screen themselves */
+ last_message = 0;
+ }
+ else /* Spectrogram mode - need to erase the popup */
+ {
+ int x, y;
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_getstringsize(last_message, &x, &y);
+#else
+ grey_getstringsize(last_message, &x, &y);
+#endif
+ /* Recalculate the size */
+ x += 6; /* 3 px of horizontal padding and */
+ y += 4; /* 2 px of vertical padding */
+
+ if(!graph_settings.orientation_vertical)
+ {
+ /* In horizontal spectrogram mode, just scroll up by Y lines */
+#ifdef HAVE_LCD_COLOR
+ xlcd_scroll_up(y);
+#else
+ grey_scroll_up(y);
+#endif
+ graph_settings.spectrogram.row -= y;
+ if(graph_settings.spectrogram.row < 0)
+ graph_settings.spectrogram.row = 0;
+ }
+ else
+ {
+ /* In vertical spectrogram mode, erase the popup */
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_set_foreground(LCD_DEFAULT_BG);
+ rb->lcd_fillrect(LCD_WIDTH-2-x, 0, LCD_WIDTH-1, y);
+ rb->lcd_set_foreground(LCD_DEFAULT_FG);
+#else
+ grey_set_foreground(GREY_WHITE);
+ grey_fillrect(LCD_WIDTH-2-x, 0, LCD_WIDTH-1, y);
+ grey_set_foreground(GREY_BLACK);
+#endif
+ }
+
+ last_message = 0;
+ }
+ }
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_update();
+#else
+ grey_update();
+#endif
+
+ graph_settings.changed.mode = false;
+ graph_settings.changed.orientation = false;
+ graph_settings.changed.scale = false;
+}
+
+void draw_lines_vertical(void)
+{
+ static int32_t max = 0, vfactor = 0, vfactor_count = 0;
+ static const int32_t hfactor =
+ Q16_DIV(LCD_WIDTH << 16, (ARRAYSIZE_PLOT) << 16),
+ bins_per_pixel = (ARRAYSIZE_PLOT) / LCD_WIDTH;
+ static bool old_scale = true;
+
+ if (old_scale != graph_settings.logarithmic)
+ old_scale = graph_settings.logarithmic, max = 0; /* reset the graph on scaling mode change */
+
+ int32_t new_max = calc_magnitudes(graph_settings.logarithmic);
+
+ if (new_max > max)
+ {
+ max = new_max;
+ vfactor = Q16_DIV(LCD_HEIGHT << 16, max); /* s15.16 */
+ vfactor_count = Q16_DIV(vfactor, bins_per_pixel << 16); /* s15.16 */
+ }
+
+ if (new_max == 0 || max == 0) /* nothing to draw */
+ return;
+
+ /* take the average of neighboring bins
+ * if we have to scale the graph horizontally */
+ int64_t bins_avg = 0;
+ bool draw = true;
+ int32_t i;
+ for (i = 0; i < ARRAYSIZE_PLOT; ++i)
+ {
+ int32_t x = 0, y = 0;
+
+ x = Q16_MUL(hfactor, i << 16) >> 16;
+ //x = (x + (1 << 15)) >> 16;
+
+ if (hfactor < 65536) /* hfactor < 0, graph compression */
+ {
+ draw = false;
+ bins_avg += plot[i];
+
+ /* fix the division by zero warning:
+ * bins_per_pixel is zero when the graph is expanding;
+ * execution won't even reach this point - this is a dummy constant
+ */
+ const int32_t div = bins_per_pixel > 0 ? bins_per_pixel : 1;
+ if ((i + 1) % div == 0)
+ {
+ y = Q16_MUL(vfactor_count, bins_avg) >> 16;
+
+ bins_avg = 0;
+ draw = true;
+ }
+ }
+ else
+ {
+ y = Q16_MUL(vfactor, plot[i]) >> 16;
+ draw = true;
+ }
+
+ if (draw)
+ {
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_vline(x, LCD_HEIGHT-1, LCD_HEIGHT-y-1);
+#else
+ grey_vline(x, LCD_HEIGHT-1, LCD_HEIGHT-y-1);
+#endif
+ }
+ }
+}
+
+void draw_lines_horizontal(void)
+{
+ static int max = 0;
+
+ static const int32_t vfactor =
+ Q16_DIV(LCD_HEIGHT << 16, (ARRAYSIZE_PLOT) << 16),
+ bins_per_pixel = (ARRAYSIZE_PLOT) / LCD_HEIGHT;
+
+ if (graph_settings.changed.scale)
+ max = 0; /* reset the graph on scaling mode change */
+
+ int32_t new_max = calc_magnitudes(graph_settings.logarithmic);
+
+ if (new_max > max)
+ max = new_max;
+
+ if (new_max == 0 || max == 0) /* nothing to draw */
+ return;
+
+ int32_t hfactor;
+
+ hfactor = Q16_DIV((LCD_WIDTH - 1) << 16, max); /* s15.16 */
+
+ /* take the average of neighboring bins
+ * if we have to scale the graph horizontally */
+ int64_t bins_avg = 0;
+ bool draw = true;
+ int32_t i;
+ for (i = 0; i < ARRAYSIZE_PLOT; ++i)
+ {
+ int32_t x = 0, y = 0;
+
+ y = Q16_MUL(vfactor, i << 16) + (1 << 15);
+ y >>= 16;
+
+ if (vfactor < 65536) /* vfactor < 0, graph compression */
+ {
+ draw = false;
+ bins_avg += plot[i];
+
+ /* fix the division by zero warning:
+ * bins_per_pixel is zero when the graph is expanding;
+ * execution won't even reach this point - this is a dummy constant
+ */
+ const int32_t div = bins_per_pixel > 0 ? bins_per_pixel : 1;
+ if ((i + 1) % div == 0)
+ {
+ bins_avg = Q16_DIV(bins_avg, div << 16);
+ x = Q16_MUL(hfactor, bins_avg) >> 16;
+
+ bins_avg = 0;
+ draw = true;
+ }
+ }
+ else
+ {
+ y = Q16_MUL(hfactor, plot[i]) >> 16;
+ draw = true;
+ }
+
+ if (draw)
+ {
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_hline(0, x, y);
+#else
+ grey_hline(0, x, y);
+#endif
+ }
+ }
+}
+
+void draw_bars_vertical(void)
+{
+ static const unsigned int bars = 20, border = 2, items = ARRAYSIZE_PLOT
+ / bars, width = (LCD_WIDTH - ((bars - 1) * border)) / bars;
+
+ calc_magnitudes(graph_settings.logarithmic);
+
+ uint64_t bars_values[bars], bars_max = 0, avg = 0;
+ unsigned int i, bars_idx = 0;
+ for (i = 0; i < ARRAYSIZE_PLOT; ++i)
+ {
+ avg += plot[i];
+ if ((i + 1) % items == 0)
+ {
+ /* Calculate the average value and keep the fractional part
+ * for some added precision */
+ avg = Q16_DIV(avg, items << 16);
+ bars_values[bars_idx] = avg;
+
+ if (bars_values[bars_idx] > bars_max)
+ bars_max = bars_values[bars_idx];
+
+ bars_idx++;
+ avg = 0;
+ }
+ }
+
+ if(bars_max == 0) /* nothing to draw */
+ return;
+
+ /* Give the graph some headroom */
+ bars_max = Q16_MUL(bars_max, float_q16(1.1));
+
+ uint64_t vfactor = Q16_DIV(LCD_HEIGHT << 16, bars_max);
+
+ for (i = 0; i < bars; ++i)
+ {
+ int x = (i) * (border + width);
+ int y;
+ y = Q16_MUL(vfactor, bars_values[i]) + (1 << 15);
+ y >>= 16;
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_fillrect(x, LCD_HEIGHT - y - 1, width, y);
+#else
+ grey_fillrect(x, LCD_HEIGHT - y - 1, width, y);
+#endif
+ }
+}
+
+void draw_bars_horizontal(void)
+{
+ static const unsigned int bars = 14, border = 3, items = ARRAYSIZE_PLOT
+ / bars, height = (LCD_HEIGHT - ((bars - 1) * border)) / bars;
+
+ calc_magnitudes(graph_settings.logarithmic);
+
+ int64_t bars_values[bars], bars_max = 0, avg = 0;
+ unsigned int i, bars_idx = 0;
+ for (i = 0; i < ARRAYSIZE_PLOT; ++i)
+ {
+ avg += plot[i];
+ if ((i + 1) % items == 0)
+ {
+ /* Calculate the average value and keep the fractional part
+ * for some added precision */
+ avg = Q16_DIV(avg, items << 16); /* s15.16 */
+ bars_values[bars_idx] = avg;
+
+ if (bars_values[bars_idx] > bars_max)
+ bars_max = bars_values[bars_idx];
+
+ bars_idx++;
+ avg = 0;
+ }
+ }
+
+ if(bars_max == 0) /* nothing to draw */
+ return;
+
+ /* Give the graph some headroom */
+ bars_max = Q16_MUL(bars_max, float_q16(1.1));
+
+ int64_t hfactor = Q16_DIV(LCD_WIDTH << 16, bars_max);
+
+ for (i = 0; i < bars; ++i)
+ {
+ int y = (i) * (border + height);
+ int x;
+ x = Q16_MUL(hfactor, bars_values[i]) + (1 << 15);
+ x >>= 16;
+
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_fillrect(0, y, x, height);
+#else
+ grey_fillrect(0, y, x, height);
+#endif
+ }
+}
+
+void draw_spectrogram_vertical(void)
+{
+ const int32_t scale_factor = ARRAYSIZE_PLOT / LCD_HEIGHT
+#ifdef HAVE_LCD_COLOR
+ ,colors_per_val_log = Q16_DIV((COLORS-1) << 16, QLOG_MAX),
+ colors_per_val_lin = Q16_DIV((COLORS-1) << 16, QLIN_MAX)
+#else
+ ,grey_vals_per_val_log = Q16_DIV(255 << 16, QLOG_MAX),
+ grey_vals_per_val_lin = Q16_DIV(255 << 16, QLIN_MAX)
+#endif
+ ;
+
+ const int32_t remaining_div =
+ (ARRAYSIZE_PLOT-scale_factor*LCD_HEIGHT) > 0 ?
+ ( Q16_DIV((scale_factor*LCD_HEIGHT) << 16,
+ (ARRAYSIZE_PLOT-scale_factor*LCD_HEIGHT) << 16)
+ + (1<<15) ) >> 16 : 0;
+
+ calc_magnitudes(graph_settings.logarithmic);
+ if(graph_settings.changed.mode || graph_settings.changed.orientation)
+ {
+ graph_settings.spectrogram.column = 0;
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_clear_display();
+#else
+ grey_clear_display();
+#endif
+ }
+
+ int i, y = LCD_HEIGHT-1, count = 0, rem_count = 0;
+ uint64_t avg = 0;
+ bool added_extra_value = false;
+ for(i = 0; i < ARRAYSIZE_PLOT; ++i)
+ {
+ if(plot[i] > 0)
+ avg += plot[i];
+ ++count;
+ ++rem_count;
+
+ /* Kinda hacky - due to the rounding in scale_factor, we try to
+ * uniformly interweave the extra values in our calculations */
+ if(remaining_div > 0 && rem_count >= remaining_div &&
+ i < (ARRAYSIZE_PLOT-1))
+ {
+ ++i;
+ if(plot[i] > 0)
+ avg += plot[i];
+ rem_count = 0;
+ added_extra_value = true;
+ }
+
+ if(count >= scale_factor)
+ {
+ if(added_extra_value)
+ { ++count; added_extra_value = false; }
+
+ int32_t color;
+
+ avg = Q16_DIV(avg, count << 16);
+
+#ifdef HAVE_LCD_COLOR
+ if(graph_settings.logarithmic)
+ color = Q16_MUL(avg, colors_per_val_log) >> 16;
+ else
+ color = Q16_MUL(avg, colors_per_val_lin) >> 16;
+ if(color >= COLORS) /* TODO These happen because we don't normalize the values to be above 1 and log() returns negative numbers. I think. */
+ color = COLORS-1;
+ else if (color < 0)
+ color = 0;
+
+#else
+ if(graph_settings.logarithmic)
+ color = Q16_MUL(avg, grey_vals_per_val_log) >> 16;
+ else
+ color = Q16_MUL(avg, grey_vals_per_val_lin) >> 16;
+ if(color > 255)
+ color = 255;
+ else if (color < 0)
+ color = 0;
+#endif
+
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_set_foreground(fft_colors[color]);
+ rb->lcd_drawpixel(graph_settings.spectrogram.column, y);
+#else
+ grey_set_foreground(255 - color);
+ grey_drawpixel(graph_settings.spectrogram.column, y);
+#endif
+
+ y--;
+
+ avg = 0;
+ count = 0;
+ }
+ if(y < 0)
+ break;
+ }
+ if(graph_settings.spectrogram.column != LCD_WIDTH-1)
+ graph_settings.spectrogram.column++;
+ else
+#ifdef HAVE_LCD_COLOR
+ xlcd_scroll_left(1);
+#else
+ grey_scroll_left(1);
+#endif
+}
+
+void draw_spectrogram_horizontal(void)
+{
+ const int32_t scale_factor = ARRAYSIZE_PLOT / LCD_WIDTH
+#ifdef HAVE_LCD_COLOR
+ ,colors_per_val_log = Q16_DIV((COLORS-1) << 16, QLOG_MAX),
+ colors_per_val_lin = Q16_DIV((COLORS-1) << 16, QLIN_MAX)
+#else
+ ,grey_vals_per_val_log = Q16_DIV(255 << 16, QLOG_MAX),
+ grey_vals_per_val_lin = Q16_DIV(255 << 16, QLIN_MAX)
+#endif
+ ;
+
+ const int32_t remaining_div =
+ (ARRAYSIZE_PLOT-scale_factor*LCD_WIDTH) > 0 ?
+ ( Q16_DIV((scale_factor*LCD_WIDTH) << 16,
+ (ARRAYSIZE_PLOT-scale_factor*LCD_WIDTH) << 16)
+ + (1<<15) ) >> 16 : 0;
+
+ calc_magnitudes(graph_settings.logarithmic);
+ if(graph_settings.changed.mode || graph_settings.changed.orientation)
+ {
+ graph_settings.spectrogram.row = 0;
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_clear_display();
+#else
+ grey_clear_display();
+#endif
+ }
+
+ int i, x = 0, count = 0, rem_count = 0;
+ uint64_t avg = 0;
+ bool added_extra_value = false;
+ for(i = 0; i < ARRAYSIZE_PLOT; ++i)
+ {
+ if(plot[i] > 0)
+ avg += plot[i];
+ ++count;
+ ++rem_count;
+
+ /* Kinda hacky - due to the rounding in scale_factor, we try to
+ * uniformly interweave the extra values in our calculations */
+ if(remaining_div > 0 && rem_count >= remaining_div &&
+ i < (ARRAYSIZE_PLOT-1))
+ {
+ ++i;
+ if(plot[i] > 0)
+ avg += plot[i];
+ rem_count = 0;
+ added_extra_value = true;
+ }
+
+ if(count >= scale_factor)
+ {
+ if(added_extra_value)
+ { ++count; added_extra_value = false; }
+
+ int32_t color;
+
+ avg = Q16_DIV(avg, count << 16);
+
+#ifdef HAVE_LCD_COLOR
+ if(graph_settings.logarithmic)
+ color = Q16_MUL(avg, colors_per_val_log) >> 16;
+ else
+ color = Q16_MUL(avg, colors_per_val_lin) >> 16;
+ if(color >= COLORS) /* TODO same as _vertical */
+ color = COLORS-1;
+ else if (color < 0)
+ color = 0;
+
+#else
+ if(graph_settings.logarithmic)
+ color = Q16_MUL(avg, grey_vals_per_val_log) >> 16;
+ else
+ color = Q16_MUL(avg, grey_vals_per_val_lin) >> 16;
+ if(color > 255)
+ color = 255;
+ else if (color < 0)
+ color = 0;
+#endif
+
+#ifdef HAVE_LCD_COLOR
+ rb->lcd_set_foreground(fft_colors[color]);
+ rb->lcd_drawpixel(x, graph_settings.spectrogram.row);
+#else
+ grey_set_foreground(255 - color);
+ grey_drawpixel(x, graph_settings.spectrogram.row);
+#endif
+
+ x++;
+
+ avg = 0;
+ count = 0;
+ }
+ if(x >= LCD_WIDTH)
+ break;
+ }
+ if(graph_settings.spectrogram.row != LCD_HEIGHT-1)
+ graph_settings.spectrogram.row++;
+ else
+#ifdef HAVE_LCD_COLOR
+ xlcd_scroll_up(1);
+#else
+ grey_scroll_up(1);
+#endif
+}
+
+/********************* End of plotting functions (modes) *********************/
+
+static long thread_stack[DEFAULT_STACK_SIZE/sizeof(long)];
+void input_thread_entry(void)
+{
+ kiss_fft_scalar * value;
+ kiss_fft_scalar left;
+ int count;
+ int idx = 0; /* offset in the buffer */
+ int fft_idx = 0; /* offset in input */
+ while(true)
+ {
+ rb->mutex_lock(&input_mutex);
+ if(!input_thread_run)
+ rb->thread_exit();
+
+ value = (kiss_fft_scalar*) rb->pcm_get_peak_buffer(&count);
+
+ if (value == 0 || count == 0)
+ {
+ rb->mutex_unlock(&input_mutex);
+ rb->yield();
+ continue;
+ /* This block can introduce discontinuities in our data. Meaning, the FFT
+ * will not be done a continuous segment of the signal. Which can be bad. Or not.
+ *
+ * Anyway, this is a demo, not a scientific tool. If you want accuracy, do a proper
+ * spectrum analysis.*/
+ }
+ else
+ {
+ idx = fft_idx = 0;
+ do
+ {
+ left = *(value + idx);
+ idx += 2;
+
+ input[fft_idx] = left;
+ fft_idx++;
+
+ if (fft_idx == ARRAYSIZE_IN)
+ break;
+ } while (idx < count);
+ }
+ if(fft_idx == ARRAYSIZE_IN) /* there are cases when we don't have enough data to fill the buffer */
+ input_thread_has_data = true;
+
+ rb->mutex_unlock(&input_mutex);
+ rb->yield();
+ }
+}
+
+
+enum plugin_status plugin_start(const void* parameter)
+{
+ (void) parameter;
+ if ((rb->audio_status() & AUDIO_STATUS_PLAY) == 0)
+ {
+ rb->splash(HZ * 2, "No track playing. Exiting..");
+ return PLUGIN_OK;
+ }
+#ifndef HAVE_LCD_COLOR
+ unsigned char *gbuf;
+ size_t gbuf_size = 0;
+ /* get the remainder of the plugin buffer */
+ gbuf = (unsigned char *) rb->plugin_get_buffer(&gbuf_size);
+
+ /* initialize the greyscale buffer.*/
+ if (!grey_init(gbuf, gbuf_size, GREY_ON_COP | GREY_BUFFERED,
+ LCD_WIDTH, LCD_HEIGHT, NULL))
+ {
+ rb->splash(HZ, "Couldn't init greyscale display");
+ return PLUGIN_ERROR;
+ }
+ grey_show(true);
+#endif
+
+#if LCD_DEPTH > 1
+ rb->lcd_set_backdrop(NULL);
+#endif
+ backlight_force_on();
+
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(true);
+#endif
+
+ /* Defaults */
+ bool run = true;
+ graph_settings.mode = 0;
+ graph_settings.logarithmic = true;
+ graph_settings.orientation_vertical = true;
+ graph_settings.window_func = 0;
+ graph_settings.changed.mode = false;
+ graph_settings.changed.scale = false;
+ graph_settings.changed.orientation = false;
+ graph_settings.spectrogram.row = 0;
+ graph_settings.spectrogram.column = 0;
+
+ bool changed_window = false;
+
+ size_t size = sizeof(buffer);
+ FFT_CFG state = FFT_ALLOC(FFT_SIZE, 0, buffer, &size);
+
+ if (state == 0)
+ {
+ DEBUGF("needed data: %i", (int) size);
+ return PLUGIN_ERROR;
+ }
+
+ unsigned int input_thread = rb->create_thread(&input_thread_entry, thread_stack, sizeof(thread_stack), 0, "fft input thread" IF_PRIO(, PRIORITY_BACKGROUND) IF_COP(, CPU));
+ rb->yield();
+ while (run)
+ {
+ rb->mutex_lock(&input_mutex);
+ if(!input_thread_has_data)
+ {
+ /* Make sure the input thread has started before doing anything else */
+ rb->mutex_unlock(&input_mutex);
+ rb->yield();
+ continue;
+ }
+ apply_window_func(graph_settings.window_func);
+ FFT_FFT(state, input, output);
+
+ if(changed_window)
+ {
+ draw(window_text[graph_settings.window_func]);
+ changed_window = false;
+ }
+ else
+ draw(0);
+
+ input_thread_has_data = false;
+ rb->mutex_unlock(&input_mutex);
+ rb->yield();
+
+ int button = rb->button_get(false);
+ switch (button)
+ {
+ case FFT_QUIT:
+ run = false;
+ break;
+ case FFT_PREV_GRAPH: {
+ graph_settings.mode--;
+ if (graph_settings.mode < 0)
+ graph_settings.mode = MODES_COUNT-1;
+ draw(modes_text[graph_settings.mode]);
+ break;
+ }
+ case FFT_NEXT_GRAPH: {
+ graph_settings.mode++;
+ if (graph_settings.mode >= MODES_COUNT)
+ graph_settings.mode = 0;
+ draw(modes_text[graph_settings.mode]);
+ break;
+ }
+ case FFT_WINDOW: {
+ changed_window = true;
+ graph_settings.window_func ++;
+ if(graph_settings.window_func >= WINDOW_COUNT)
+ graph_settings.window_func = 0;
+ break;
+ }
+ case FFT_SCALE: {
+ graph_settings.logarithmic = !graph_settings.logarithmic;
+ draw(scales_text[graph_settings.logarithmic ? 1 : 0]);
+ break;
+ }
+ case FFT_ORIENTATION: {
+ graph_settings.orientation_vertical = !graph_settings.orientation_vertical;
+ draw(0);
+ break;
+ }
+ default: {
+ if (rb->default_event_handler(button) == SYS_USB_CONNECTED)
+ return PLUGIN_USB_CONNECTED;
+ }
+
+ }
+ }
+
+ /* Handle our input thread. We haven't yield()'d since our last mutex_unlock, so we know we have the mutex */
+ rb->mutex_lock(&input_mutex);
+ input_thread_run = false;
+ rb->mutex_unlock(&input_mutex);
+ rb->thread_wait(input_thread);
+
+#ifdef HAVE_ADJUSTABLE_CPU_FREQ
+ rb->cpu_boost(false);
+#endif
+#ifndef HAVE_LCD_COLOR
+ grey_release();
+#endif
+ backlight_use_settings();
+ return PLUGIN_OK;
+}
diff --git a/apps/plugins/fft/fft.make b/apps/plugins/fft/fft.make
new file mode 100644
index 0000000000..b14566ca58
--- /dev/null
+++ b/apps/plugins/fft/fft.make
@@ -0,0 +1,27 @@
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+
+FFTSRCDIR := $(APPSDIR)/plugins/fft
+FFTBUILDDIR := $(BUILDDIR)/apps/plugins/fft
+
+ROCKS += $(FFTBUILDDIR)/fft.rock
+
+FFT_SRC := $(call preprocess, $(FFTSRCDIR)/SOURCES)
+FFT_OBJ := $(call c2obj, $(FFT_SRC))
+
+# add source files to OTHER_SRC to get automatic dependencies
+OTHER_SRC += $(FFT_SRC)
+
+FFTFLAGS = $(filter-out -O%,$(PLUGINFLAGS)) -O3 -DFIXED_POINT=16
+
+$(FFTBUILDDIR)/fft.rock: $(FFT_OBJ)
+
+$(FFTBUILDDIR)/%.o: $(FFTSRCDIR)/%.c $(FFTSRCDIR)/fft.make
+ $(SILENT)mkdir -p $(dir $@)
+ $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) -I$(dir $<) $(FFTFLAGS) -c $< -o $@
diff --git a/apps/plugins/fft/kiss_fft.c b/apps/plugins/fft/kiss_fft.c
new file mode 100644
index 0000000000..05db6288fe
--- /dev/null
+++ b/apps/plugins/fft/kiss_fft.c
@@ -0,0 +1,428 @@
+/*
+Copyright (c) 2003-2004, Mark Borgerding
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "_kiss_fft_guts.h"
+/* The guts header contains all the multiplication and addition macros that are defined for
+ fixed or floating point complex numbers. It also delares the kf_ internal functions.
+ */
+
+static kiss_fft_cpx *scratchbuf=NULL;
+static size_t nscratchbuf=0;
+static kiss_fft_cpx *tmpbuf=NULL;
+static size_t ntmpbuf=0;
+
+#define CHECKBUF(buf,nbuf,n) \
+ do { \
+ if ( nbuf < (size_t)(n) ) {\
+ DEBUGF("CHECKBUF NOT IMPLEMENTED!");\
+ break;\
+ } \
+ }while(0)
+
+
+static void kf_bfly2(
+ kiss_fft_cpx * Fout,
+ const size_t fstride,
+ const kiss_fft_cfg st,
+ int m
+ )
+{
+ kiss_fft_cpx * Fout2;
+ kiss_fft_cpx * tw1 = st->twiddles;
+ kiss_fft_cpx t;
+ Fout2 = Fout + m;
+ do{
+ C_FIXDIV(*Fout,2); C_FIXDIV(*Fout2,2);
+
+ C_MUL (t, *Fout2 , *tw1);
+ tw1 += fstride;
+ C_SUB( *Fout2 , *Fout , t );
+ C_ADDTO( *Fout , t );
+ ++Fout2;
+ ++Fout;
+ }while (--m);
+}
+
+static void kf_bfly4(
+ kiss_fft_cpx * Fout,
+ const size_t fstride,
+ const kiss_fft_cfg st,
+ const size_t m
+ )
+{
+ kiss_fft_cpx *tw1,*tw2,*tw3;
+ kiss_fft_cpx scratch[6];
+ size_t k=m;
+ const size_t m2=2*m;
+ const size_t m3=3*m;
+
+ tw3 = tw2 = tw1 = st->twiddles;
+
+ do {
+ C_FIXDIV(*Fout,4); C_FIXDIV(Fout[m],4); C_FIXDIV(Fout[m2],4); C_FIXDIV(Fout[m3],4);
+
+ C_MUL(scratch[0],Fout[m] , *tw1 );
+ C_MUL(scratch[1],Fout[m2] , *tw2 );
+ C_MUL(scratch[2],Fout[m3] , *tw3 );
+
+ C_SUB( scratch[5] , *Fout, scratch[1] );
+ C_ADDTO(*Fout, scratch[1]);
+ C_ADD( scratch[3] , scratch[0] , scratch[2] );
+ C_SUB( scratch[4] , scratch[0] , scratch[2] );
+ C_SUB( Fout[m2], *Fout, scratch[3] );
+ tw1 += fstride;
+ tw2 += fstride*2;
+ tw3 += fstride*3;
+ C_ADDTO( *Fout , scratch[3] );
+
+ if(st->inverse) {
+ Fout[m].r = scratch[5].r - scratch[4].i;
+ Fout[m].i = scratch[5].i + scratch[4].r;
+ Fout[m3].r = scratch[5].r + scratch[4].i;
+ Fout[m3].i = scratch[5].i - scratch[4].r;
+ }else{
+ Fout[m].r = scratch[5].r + scratch[4].i;
+ Fout[m].i = scratch[5].i - scratch[4].r;
+ Fout[m3].r = scratch[5].r - scratch[4].i;
+ Fout[m3].i = scratch[5].i + scratch[4].r;
+ }
+ ++Fout;
+ }while(--k);
+}
+
+static void kf_bfly3(
+ kiss_fft_cpx * Fout,
+ const size_t fstride,
+ const kiss_fft_cfg st,
+ size_t m
+ )
+{
+ size_t k=m;
+ const size_t m2 = 2*m;
+ kiss_fft_cpx *tw1,*tw2;
+ kiss_fft_cpx scratch[5];
+ kiss_fft_cpx epi3;
+ epi3 = st->twiddles[fstride*m];
+
+ tw1=tw2=st->twiddles;
+
+ do{
+ C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3);
+
+ C_MUL(scratch[1],Fout[m] , *tw1);
+ C_MUL(scratch[2],Fout[m2] , *tw2);
+
+ C_ADD(scratch[3],scratch[1],scratch[2]);
+ C_SUB(scratch[0],scratch[1],scratch[2]);
+ tw1 += fstride;
+ tw2 += fstride*2;
+
+ Fout[m].r = Fout->r - HALF_OF(scratch[3].r);
+ Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
+
+ C_MULBYSCALAR( scratch[0] , epi3.i );
+
+ C_ADDTO(*Fout,scratch[3]);
+
+ Fout[m2].r = Fout[m].r + scratch[0].i;
+ Fout[m2].i = Fout[m].i - scratch[0].r;
+
+ Fout[m].r -= scratch[0].i;
+ Fout[m].i += scratch[0].r;
+
+ ++Fout;
+ }while(--k);
+}
+
+static void kf_bfly5(
+ kiss_fft_cpx * Fout,
+ const size_t fstride,
+ const kiss_fft_cfg st,
+ int m
+ )
+{
+ kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
+ int u;
+ kiss_fft_cpx scratch[13];
+ kiss_fft_cpx * twiddles = st->twiddles;
+ kiss_fft_cpx *tw;
+ kiss_fft_cpx ya,yb;
+ ya = twiddles[fstride*m];
+ yb = twiddles[fstride*2*m];
+
+ Fout0=Fout;
+ Fout1=Fout0+m;
+ Fout2=Fout0+2*m;
+ Fout3=Fout0+3*m;
+ Fout4=Fout0+4*m;
+
+ tw=st->twiddles;
+ for ( u=0; u<m; ++u ) {
+ C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
+ scratch[0] = *Fout0;
+
+ C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
+ C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
+ C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
+ C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
+
+ C_ADD( scratch[7],scratch[1],scratch[4]);
+ C_SUB( scratch[10],scratch[1],scratch[4]);
+ C_ADD( scratch[8],scratch[2],scratch[3]);
+ C_SUB( scratch[9],scratch[2],scratch[3]);
+
+ Fout0->r += scratch[7].r + scratch[8].r;
+ Fout0->i += scratch[7].i + scratch[8].i;
+
+ scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
+ scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
+
+ scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
+ scratch[6].i = -S_MUL(scratch[10].r,ya.i) - S_MUL(scratch[9].r,yb.i);
+
+ C_SUB(*Fout1,scratch[5],scratch[6]);
+ C_ADD(*Fout4,scratch[5],scratch[6]);
+
+ scratch[11].r = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
+ scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
+ scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
+ scratch[12].i = S_MUL(scratch[10].r,yb.i) - S_MUL(scratch[9].r,ya.i);
+
+ C_ADD(*Fout2,scratch[11],scratch[12]);
+ C_SUB(*Fout3,scratch[11],scratch[12]);
+
+ ++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
+ }
+}
+
+/* perform the butterfly for one stage of a mixed radix FFT */
+static void kf_bfly_generic(
+ kiss_fft_cpx * Fout,
+ const size_t fstride,
+ const kiss_fft_cfg st,
+ int m,
+ int p
+ )
+{
+ int u,k,q1,q;
+ kiss_fft_cpx * twiddles = st->twiddles;
+ kiss_fft_cpx t;
+ int Norig = st->nfft;
+
+ CHECKBUF(scratchbuf,nscratchbuf,p);
+
+ for ( u=0; u<m; ++u ) {
+ k=u;
+ for ( q1=0 ; q1<p ; ++q1 ) {
+ scratchbuf[q1] = Fout[ k ];
+ C_FIXDIV(scratchbuf[q1],p);
+ k += m;
+ }
+
+ k=u;
+ for ( q1=0 ; q1<p ; ++q1 ) {
+ int twidx=0;
+ Fout[ k ] = scratchbuf[0];
+ for (q=1;q<p;++q ) {
+ twidx += fstride * k;
+ if (twidx>=Norig) twidx-=Norig;
+ C_MUL(t,scratchbuf[q] , twiddles[twidx] );
+ C_ADDTO( Fout[ k ] ,t);
+ }
+ k += m;
+ }
+ }
+}
+
+static
+void kf_work(
+ kiss_fft_cpx * Fout,
+ const kiss_fft_cpx * f,
+ const size_t fstride,
+ int in_stride,
+ int * factors,
+ const kiss_fft_cfg st
+ )
+{
+ kiss_fft_cpx * Fout_beg=Fout;
+ const int p=*factors++; /* the radix */
+ const int m=*factors++; /* stage's fft length/p */
+ const kiss_fft_cpx * Fout_end = Fout + p*m;
+
+#ifdef _OPENMP
+ // use openmp extensions at the
+ // top-level (not recursive)
+ if (fstride==1) {
+ int k;
+
+ // execute the p different work units in different threads
+# pragma omp parallel for
+ for (k=0;k<p;++k)
+ kf_work( Fout +k*m, f+ fstride*in_stride*k,fstride*p,in_stride,factors,st);
+ // all threads have joined by this point
+
+ switch (p) {
+ case 2: kf_bfly2(Fout,fstride,st,m); break;
+ case 3: kf_bfly3(Fout,fstride,st,m); break;
+ case 4: kf_bfly4(Fout,fstride,st,m); break;
+ case 5: kf_bfly5(Fout,fstride,st,m); break;
+ default: kf_bfly_generic(Fout,fstride,st,m,p); break;
+ }
+ return;
+ }
+#endif
+
+ if (m==1) {
+ do{
+ *Fout = *f;
+ f += fstride*in_stride;
+ }while(++Fout != Fout_end );
+ }else{
+ do{
+ // recursive call:
+ // DFT of size m*p performed by doing
+ // p instances of smaller DFTs of size m,
+ // each one takes a decimated version of the input
+ kf_work( Fout , f, fstride*p, in_stride, factors,st);
+ f += fstride*in_stride;
+ }while( (Fout += m) != Fout_end );
+ }
+
+ Fout=Fout_beg;
+
+ // recombine the p smaller DFTs
+ switch (p) {
+ case 2: kf_bfly2(Fout,fstride,st,m); break;
+ case 3: kf_bfly3(Fout,fstride,st,m); break;
+ case 4: kf_bfly4(Fout,fstride,st,m); break;
+ case 5: kf_bfly5(Fout,fstride,st,m); break;
+ default: kf_bfly_generic(Fout,fstride,st,m,p); break;
+ }
+}
+
+/* facbuf is populated by p1,m1,p2,m2, ...
+ where
+ p[i] * m[i] = m[i-1]
+ m0 = n */
+static
+void kf_factor(int n,int * facbuf)
+{
+ int p=4;
+ int32_t floor_sqrt = fp_sqrt(n, 15) >> 15;
+
+ /*factor out powers of 4, powers of 2, then any remaining primes */
+ do {
+ while (n % p) {
+ switch (p) {
+ case 4: p = 2; break;
+ case 2: p = 3; break;
+ default: p += 2; break;
+ }
+ if (p > floor_sqrt)
+ p = n; /* no more factors, skip to end */
+ }
+ n /= p;
+ *facbuf++ = p;
+ *facbuf++ = n;
+ } while (n > 1);
+}
+
+/*
+ *
+ * User-callable function to allocate all necessary storage space for the fft.
+ *
+ * The return value is a contiguous block of memory, allocated with malloc. As such,
+ * It can be freed with free(), rather than a kiss_fft-specific function.
+ * */
+kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem )
+{
+ kiss_fft_cfg st=NULL;
+ size_t memneeded = sizeof(struct kiss_fft_state)
+ + sizeof(kiss_fft_cpx)*(nfft-1); /* twiddle factors*/
+
+ if ( lenmem==NULL ) {
+ DEBUGF("This version of kiss fft can't use malloc");
+ return st;
+ /* st = ( kiss_fft_cfg)KISS_FFT_MALLOC( memneeded ); */
+ }else{
+ if (mem != NULL && *lenmem >= memneeded)
+ st = (kiss_fft_cfg)mem;
+ *lenmem = memneeded;
+ }
+ if (st) {
+ int i;
+ st->nfft=nfft;
+ st->inverse = inverse_fft;
+
+ for (i=0;i<nfft;++i) {
+ /* const double pi=3.141592653589793238462643383279502884197169399375105820974944;
+ double phase = -2*pi*i / nfft; */
+ if (st->inverse)
+ DEBUGF("Inverse FFT not implemented!"); /* kf_cexp(st->twiddles+i, -1*i, nfft ); */
+ else
+ kf_cexp( st->twiddles+i, i, nfft );
+ }
+
+ kf_factor(nfft,st->factors);
+ }
+ return st;
+}
+
+
+
+
+void kiss_fft_stride(kiss_fft_cfg st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
+{
+ if (fin == fout) {
+ CHECKBUF(tmpbuf,ntmpbuf,st->nfft);
+ kf_work(tmpbuf,fin,1,in_stride, st->factors,st);
+ memcpy(fout,tmpbuf,sizeof(kiss_fft_cpx)*st->nfft);
+ }else{
+ kf_work( fout, fin, 1,in_stride, st->factors,st );
+ }
+}
+
+void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
+{
+ kiss_fft_stride(cfg,fin,fout,1);
+}
+
+
+/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the
+ buffers from CHECKBUF
+ */
+void kiss_fft_cleanup(void)
+{
+ /* free(scratchbuf); */
+ scratchbuf = NULL;
+ nscratchbuf=0;
+ /* free(tmpbuf); */
+ tmpbuf=NULL;
+ ntmpbuf=0;
+}
+
+int kiss_fft_next_fast_size(int n)
+{
+ while(1) {
+ int m=n;
+ while ( (m%2) == 0 ) m/=2;
+ while ( (m%3) == 0 ) m/=3;
+ while ( (m%5) == 0 ) m/=5;
+ if (m<=1)
+ break; /* n is completely factorable by twos, threes, and fives */
+ n++;
+ }
+ return n;
+}
diff --git a/apps/plugins/fft/kiss_fft.h b/apps/plugins/fft/kiss_fft.h
new file mode 100644
index 0000000000..35c864832a
--- /dev/null
+++ b/apps/plugins/fft/kiss_fft.h
@@ -0,0 +1,119 @@
+#ifndef KISS_FFT_H
+#define KISS_FFT_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <malloc.h>
+#include "plugin.h"
+#include "lib/helper.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ ATTENTION!
+ If you would like a :
+ -- a utility that will handle the caching of fft objects
+ -- real-only (no imaginary time component ) FFT
+ -- a multi-dimensional FFT
+ -- a command-line utility to perform ffts
+ -- a command-line utility to perform fast-convolution filtering
+
+ Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c
+ in the tools/ directory.
+*/
+
+#define KISS_FFT_MALLOC malloc
+
+
+#ifdef FIXED_POINT
+#include <inttypes.h>
+# if (FIXED_POINT == 32)
+# define kiss_fft_scalar int32_t
+# else
+# define kiss_fft_scalar int16_t
+# endif
+#else
+# ifndef kiss_fft_scalar
+/* default is float */
+# define kiss_fft_scalar float
+# endif
+#endif
+
+typedef struct {
+ kiss_fft_scalar r;
+ kiss_fft_scalar i;
+}kiss_fft_cpx;
+
+typedef struct kiss_fft_state* kiss_fft_cfg;
+
+/*
+ * kiss_fft_alloc
+ *
+ * Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
+ *
+ * typical usage: kiss_fft_cfg mycfg=kiss_fft_alloc(1024,0,NULL,NULL);
+ *
+ * The return value from fft_alloc is a cfg buffer used internally
+ * by the fft routine or NULL.
+ *
+ * If lenmem is NULL, then kiss_fft_alloc will allocate a cfg buffer using malloc.
+ * The returned value should be free()d when done to avoid memory leaks.
+ *
+ * The state can be placed in a user supplied buffer 'mem':
+ * If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
+ * then the function places the cfg in mem and the size used in *lenmem
+ * and returns mem.
+ *
+ * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
+ * then the function returns NULL and places the minimum cfg
+ * buffer size in *lenmem.
+ * */
+
+kiss_fft_cfg kiss_fft_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem);
+
+/*
+ * kiss_fft(cfg,in_out_buf)
+ *
+ * Perform an FFT on a complex input buffer.
+ * for a forward FFT,
+ * fin should be f[0] , f[1] , ... ,f[nfft-1]
+ * fout will be F[0] , F[1] , ... ,F[nfft-1]
+ * Note that each element is complex and can be accessed like
+ f[k].r and f[k].i
+ * */
+void kiss_fft(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
+
+/*
+ A more generic version of the above function. It reads its input from every Nth sample.
+ * */
+void kiss_fft_stride(kiss_fft_cfg cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int fin_stride);
+
+/* If kiss_fft_alloc allocated a buffer, it is one contiguous
+ buffer and can be simply free()d when no longer needed*/
+#define kiss_fft_free free
+
+/*
+ Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up
+ your compiler output to call this before you exit.
+*/
+void kiss_fft_cleanup(void);
+
+
+/*
+ * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5)
+ */
+int kiss_fft_next_fast_size(int n);
+
+/* for real ffts, we need an even size */
+#define kiss_fftr_next_fast_size_real(n) \
+ (kiss_fft_next_fast_size( ((n)+1)>>1)<<1)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/apps/plugins/fft/kiss_fftr.c b/apps/plugins/fft/kiss_fftr.c
new file mode 100644
index 0000000000..7fa29b98e8
--- /dev/null
+++ b/apps/plugins/fft/kiss_fftr.c
@@ -0,0 +1,153 @@
+/*
+Copyright (c) 2003-2004, Mark Borgerding
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "kiss_fftr.h"
+#include "_kiss_fft_guts.h"
+
+kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem)
+{
+ int i;
+ kiss_fftr_cfg st = NULL;
+ size_t subsize, memneeded;
+
+ if (nfft & 1) {
+ DEBUGF("Real FFT optimization must be even.\n");
+ return NULL;
+ }
+ nfft >>= 1;
+
+ kiss_fft_alloc (nfft, inverse_fft, NULL, &subsize);
+ memneeded = sizeof(struct kiss_fftr_state) + subsize + sizeof(kiss_fft_cpx) * ( nfft * 3 / 2);
+
+ if (lenmem == NULL) {
+ DEBUGF("Cannot use malloc!"); /*st = (kiss_fftr_cfg) KISS_FFT_MALLOC (memneeded);*/
+ } else {
+ if (*lenmem >= memneeded)
+ st = (kiss_fftr_cfg) mem;
+ *lenmem = memneeded;
+ }
+ if (!st)
+ return NULL;
+
+ st->substate = (kiss_fft_cfg) (st + 1); /*just beyond kiss_fftr_state struct */
+ st->tmpbuf = (kiss_fft_cpx *) (((char *) st->substate) + subsize);
+ st->super_twiddles = st->tmpbuf + nfft;
+ kiss_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
+
+ for (i = 0; i < nfft/2; ++i) {
+ /*double phase =
+ -3.14159265358979323846264338327 * ((double) (i+1) / nfft + .5);*/
+ if (inverse_fft)
+ {
+ DEBUGF("Inverse FFT not implemented!"); /*phase *= -1;*/
+ }
+
+ kf_cexp_round (st->super_twiddles+i, i+1, nfft);
+ }
+ return st;
+}
+
+void kiss_fftr(kiss_fftr_cfg st,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata)
+{
+ /* input buffer timedata is stored row-wise */
+ int k,ncfft;
+ kiss_fft_cpx fpnk,fpk,f1k,f2k,tw,tdc;
+
+ if ( st->substate->inverse) {
+ DEBUGF("kiss fft usage error: improper alloc\n");
+ return;
+ }
+
+ ncfft = st->substate->nfft;
+
+ /*perform the parallel fft of two real signals packed in real,imag*/
+ kiss_fft( st->substate , (const kiss_fft_cpx*)timedata, st->tmpbuf );
+ /* The real part of the DC element of the frequency spectrum in st->tmpbuf
+ * contains the sum of the even-numbered elements of the input time sequence
+ * The imag part is the sum of the odd-numbered elements
+ *
+ * The sum of tdc.r and tdc.i is the sum of the input time sequence.
+ * yielding DC of input time sequence
+ * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1...
+ * yielding Nyquist bin of input time sequence
+ */
+
+ tdc.r = st->tmpbuf[0].r;
+ tdc.i = st->tmpbuf[0].i;
+ C_FIXDIV(tdc,2);
+ CHECK_OVERFLOW_OP(tdc.r ,+, tdc.i);
+ CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
+ freqdata[0].r = tdc.r + tdc.i;
+ freqdata[ncfft].r = tdc.r - tdc.i;
+#ifdef USE_SIMD
+ freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
+#else
+ freqdata[ncfft].i = freqdata[0].i = 0;
+#endif
+
+ for ( k=1;k <= ncfft/2 ; ++k ) {
+ fpk = st->tmpbuf[k];
+ fpnk.r = st->tmpbuf[ncfft-k].r;
+ fpnk.i = - st->tmpbuf[ncfft-k].i;
+ C_FIXDIV(fpk,2);
+ C_FIXDIV(fpnk,2);
+
+ C_ADD( f1k, fpk , fpnk );
+ C_SUB( f2k, fpk , fpnk );
+ C_MUL( tw , f2k , st->super_twiddles[k-1]);
+
+ freqdata[k].r = HALF_OF(f1k.r + tw.r);
+ freqdata[k].i = HALF_OF(f1k.i + tw.i);
+ freqdata[ncfft-k].r = HALF_OF(f1k.r - tw.r);
+ freqdata[ncfft-k].i = HALF_OF(tw.i - f1k.i);
+ }
+}
+
+void kiss_fftri(kiss_fftr_cfg st,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata)
+{
+ /* input buffer timedata is stored row-wise */
+ int k, ncfft;
+
+ if (st->substate->inverse == 0) {
+ DEBUGF("kiss fft usage error: improper alloc\n");
+ return;
+ }
+
+ ncfft = st->substate->nfft;
+
+ st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r;
+ st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r;
+ C_FIXDIV(st->tmpbuf[0],2);
+
+ for (k = 1; k <= ncfft / 2; ++k) {
+ kiss_fft_cpx fk, fnkc, fek, fok, tmp;
+ fk = freqdata[k];
+ fnkc.r = freqdata[ncfft - k].r;
+ fnkc.i = -freqdata[ncfft - k].i;
+ C_FIXDIV( fk , 2 );
+ C_FIXDIV( fnkc , 2 );
+
+ C_ADD (fek, fk, fnkc);
+ C_SUB (tmp, fk, fnkc);
+ C_MUL (fok, tmp, st->super_twiddles[k-1]);
+ C_ADD (st->tmpbuf[k], fek, fok);
+ C_SUB (st->tmpbuf[ncfft - k], fek, fok);
+#ifdef USE_SIMD
+ st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
+#else
+ st->tmpbuf[ncfft - k].i *= -1;
+#endif
+ }
+ kiss_fft (st->substate, st->tmpbuf, (kiss_fft_cpx *) timedata);
+}
diff --git a/apps/plugins/fft/kiss_fftr.h b/apps/plugins/fft/kiss_fftr.h
new file mode 100644
index 0000000000..19018a05c8
--- /dev/null
+++ b/apps/plugins/fft/kiss_fftr.h
@@ -0,0 +1,54 @@
+#ifndef KISS_FTR_H
+#define KISS_FTR_H
+
+#include "kiss_fft.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+
+ Real optimized version can save about 45% cpu time vs. complex fft of a real seq.
+
+
+
+ */
+
+struct kiss_fftr_state{
+ kiss_fft_cfg substate;
+ kiss_fft_cpx * tmpbuf;
+ kiss_fft_cpx * super_twiddles;
+#ifdef USE_SIMD
+ long pad;
+#endif
+};
+typedef struct kiss_fftr_state *kiss_fftr_cfg;
+
+
+kiss_fftr_cfg kiss_fftr_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem);
+/*
+ nfft must be even
+
+ If you don't care to allocate space, use mem = lenmem = NULL
+*/
+
+
+void kiss_fftr(kiss_fftr_cfg cfg,const kiss_fft_scalar *timedata,kiss_fft_cpx *freqdata);
+/*
+ input timedata has nfft scalar points
+ output freqdata has nfft/2+1 complex points
+*/
+
+void kiss_fftri(kiss_fftr_cfg cfg,const kiss_fft_cpx *freqdata,kiss_fft_scalar *timedata);
+/*
+ input freqdata has nfft/2+1 complex points
+ output timedata has nfft scalar points
+*/
+
+#define kiss_fftr_free free
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/apps/plugins/fft/math.c b/apps/plugins/fft/math.c
new file mode 100644
index 0000000000..c00804fcc8
--- /dev/null
+++ b/apps/plugins/fft/math.c
@@ -0,0 +1,13 @@
+#include "math.h"
+
+int64_t fsqrt64(int64_t a, unsigned int fracbits)
+{
+ int64_t b = a/2 + (1 << fracbits); /* initial approximation */
+ unsigned int n;
+ const unsigned int iterations = 3; /* very rough approximation */
+
+ for (n = 0; n < iterations; ++n)
+ b = (b + (((int64_t)(a) << fracbits)/b))/2;
+
+ return b;
+}
diff --git a/apps/plugins/fft/math.h b/apps/plugins/fft/math.h
new file mode 100644
index 0000000000..450b9aafcb
--- /dev/null
+++ b/apps/plugins/fft/math.h
@@ -0,0 +1,28 @@
+#ifndef __MATH_H_
+#define __MATH_H_
+
+#include <inttypes.h>
+#include <math.h>
+#include "lib/fixedpoint.h"
+
+#define Q_MUL(a, b, bits) (( (int64_t) (a) * (int64_t) (b) ) >> (bits))
+#define Q15_MUL(a, b) Q_MUL(a,b,15)
+#define Q16_MUL(a, b) Q_MUL(a,b,16)
+
+#define Q_DIV(a, b, bits) ( (((int64_t) (a)) << (bits)) / (b) )
+#define Q15_DIV(a, b) Q_DIV(a,b,15)
+#define Q16_DIV(a, b) Q_DIV(a,b,16)
+
+#define float_q(a, bits) (int32_t)( ((float)(a)) *(1<<(bits)))
+#define float_q15(a) float_q(a, 15)
+#define float_q16(a) float_q(a, 16)
+
+/**
+ * Fixed point square root via Newton-Raphson.
+ * @param a square root argument.
+ * @param fracbits specifies number of fractional bits in argument.
+ * @return Square root of argument in same fixed point format as input.
+ */
+int64_t fsqrt64(int64_t a, unsigned int fracbits);
+
+#endif
diff --git a/firmware/export/pcm.h b/firmware/export/pcm.h
index 444e0c9c09..b9ad913100 100644
--- a/firmware/export/pcm.h
+++ b/firmware/export/pcm.h
@@ -75,6 +75,7 @@ void pcm_play_data(pcm_more_callback_type get_more,
unsigned char* start, size_t size);
void pcm_calculate_peaks(int *left, int *right);
+const void* pcm_get_peak_buffer(int* count);
size_t pcm_get_bytes_waiting(void);
void pcm_play_stop(void);
diff --git a/firmware/pcm.c b/firmware/pcm.c
index cddb2eaecd..0e89cb90c9 100644
--- a/firmware/pcm.c
+++ b/firmware/pcm.c
@@ -183,6 +183,11 @@ void pcm_calculate_peaks(int *left, int *right)
*right = peaks[1];
}
+const void* pcm_get_peak_buffer(int * count)
+{
+ return pcm_play_dma_get_peak_buffer(count);
+}
+
/****************************************************************************
* Functions that do not require targeted implementation but only a targeted
* interface