66
77/*
88 * Vectorized implementation of a Postgres float{4,8}_accum() transition
9- * function for a single type. They use the same Youngs-Cramer state, but for
10- * AVG we can skip calculating the Sxx variable.
9+ * function for a single type.
1110 */
1211
1312#ifdef GENERATE_DISPATCH_TABLE
1716extern VectorAggFunctions FUNCTION_NAME (argdef );
1817
1918/*
20- * Helper macros to generate the cases for the given argument type. We support
21- * different aggregate functions based on whether we calculate the Sxx variable.
19+ * Helper macros to generate the cases for the given argument type.
2220 */
23- #ifdef NEED_SXX
2421#define ACCUM_CASE_HELPER (PG_TYPE ) \
2522 case F_STDDEV_##PG_TYPE: \
2623 case F_STDDEV_SAMP_##PG_TYPE: \
2724 case F_STDDEV_POP_##PG_TYPE: \
2825 case F_VARIANCE_##PG_TYPE: \
2926 case F_VAR_SAMP_##PG_TYPE: \
30- case F_VAR_POP_##PG_TYPE:
31- #else
32- #define ACCUM_CASE_HELPER (PG_TYPE ) case F_AVG_##PG_TYPE:
33- #endif
27+ case F_VAR_POP_##PG_TYPE: \
28+ case F_AVG_##PG_TYPE:
3429
3530#define ACCUM_CASE (PG_TYPE ) ACCUM_CASE_HELPER(PG_TYPE)
3631
@@ -49,9 +44,7 @@ typedef struct
4944{
5045 double N ;
5146 double Sx ;
52- #ifdef NEED_SXX
5347 double Sxx ;
54- #endif
5548} FUNCTION_NAME (state );
5649
5750static void
@@ -84,17 +77,7 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull)
8477 */
8578 ((float8 * ) ARR_DATA_PTR (result ))[0 ] = state -> N ;
8679 ((float8 * ) ARR_DATA_PTR (result ))[1 ] = state -> Sx ;
87- ((float8 * ) ARR_DATA_PTR (result ))[2 ] =
88- /*
89- * Sxx should be NaN if any of the inputs are infinite or NaN. This is
90- * checked by float8_combine even if it's not used for the actual
91- * calculations.
92- */
93- 0. * state -> Sx
94- #ifdef NEED_SXX
95- + state -> Sxx
96- #endif
97- ;
80+ ((float8 * ) ARR_DATA_PTR (result ))[2 ] = state -> Sxx ;
9881
9982 * out_result = PointerGetDatum (result );
10083 * out_isnull = false;
@@ -104,12 +87,8 @@ FUNCTION_NAME(emit)(void *agg_state, Datum *out_result, bool *out_isnull)
10487 * Youngs-Cramer update for rows after the first.
10588 */
10689static pg_attribute_always_inline void
107- FUNCTION_NAME (update )(const uint64 * filter , const CTYPE * values , int row , double * N , double * Sx
108- #ifdef NEED_SXX
109- ,
110- double * Sxx
111- #endif
112- )
90+ FUNCTION_NAME (update )(const uint64 * filter , const CTYPE * values , int row , double * N , double * Sx ,
91+ double * Sxx )
11392{
11493 const CTYPE newval = values [row ];
11594 if (!arrow_row_is_valid (filter , row ))
@@ -123,11 +102,9 @@ FUNCTION_NAME(update)(const uint64 *filter, const CTYPE *values, int row, double
123102 */
124103 const double newN = * N + 1.0 ;
125104 const double newSx = * Sx + newval ;
126- #ifdef NEED_SXX
127105 Assert (* N > 0.0 );
128106 const double tmp = newval * newN - newSx ;
129107 * Sxx += tmp * tmp / (* N * newN );
130- #endif
131108
132109 * N = newN ;
133110 * Sx = newSx ;
@@ -137,67 +114,43 @@ FUNCTION_NAME(update)(const uint64 *filter, const CTYPE *values, int row, double
137114 * Combine two Youngs-Cramer states following the float8_combine() function.
138115 */
139116static pg_attribute_always_inline void
140- FUNCTION_NAME (combine )(double * inout_N , double * inout_Sx ,
141- #ifdef NEED_SXX
142- double * inout_Sxx ,
143- #endif
144- double N2 , double Sx2
145- #ifdef NEED_SXX
146- ,
147- double Sxx2
148- #endif
149- )
117+ FUNCTION_NAME (combine )(double * inout_N , double * inout_Sx , double * inout_Sxx , double N2 , double Sx2 ,
118+ double Sxx2 )
150119{
151120 const double N1 = * inout_N ;
152121 const double Sx1 = * inout_Sx ;
153- #ifdef NEED_SXX
154122 const double Sxx1 = * inout_Sxx ;
155- #endif
156123
157124 if (unlikely (N1 == 0 ))
158125 {
159126 * inout_N = N2 ;
160127 * inout_Sx = Sx2 ;
161- #ifdef NEED_SXX
162128 * inout_Sxx = Sxx2 ;
163- #endif
164129 return ;
165130 }
166131
167132 if (unlikely (N2 == 0 ))
168133 {
169134 * inout_N = N1 ;
170135 * inout_Sx = Sx1 ;
171- #ifdef NEED_SXX
172136 * inout_Sxx = Sxx1 ;
173- #endif
174137 return ;
175138 }
176139
177140 const double combinedN = N1 + N2 ;
178141 const double combinedSx = Sx1 + Sx2 ;
179- #ifdef NEED_SXX
180142 const double tmp = Sx1 / N1 - Sx2 / N2 ;
181143 const double combinedSxx = Sxx1 + Sxx2 + N1 * N2 * tmp * tmp / combinedN ;
182- #endif
183144
184145 * inout_N = combinedN ;
185146 * inout_Sx = combinedSx ;
186- #ifdef NEED_SXX
187147 * inout_Sxx = combinedSxx ;
188- #endif
189148}
190149
191- #ifdef NEED_SXX
192150#define UPDATE (filter , values , row , N , Sx , Sxx ) \
193151 FUNCTION_NAME(update)(filter, values, row, N, Sx, Sxx)
194152#define COMBINE (inout_N , inout_Sx , inout_Sxx , N2 , Sx2 , Sxx2 ) \
195153 FUNCTION_NAME(combine)(inout_N, inout_Sx, inout_Sxx, N2, Sx2, Sxx2)
196- #else
197- #define UPDATE (filter , values , row , N , Sx , Sxx ) FUNCTION_NAME(update)(filter, values, row, N, Sx)
198- #define COMBINE (inout_N , inout_Sx , inout_Sxx , N2 , Sx2 , Sxx2 ) \
199- FUNCTION_NAME(combine)(inout_N, inout_Sx, N2, Sx2)
200- #endif
201154
202155static pg_attribute_always_inline void
203156FUNCTION_NAME (vector_impl )(void * agg_state , size_t n , const CTYPE * values , const uint64 * filter ,
@@ -214,13 +167,10 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const
214167 */
215168 double Narray [UNROLL_SIZE ] = { 0 };
216169 double Sxarray [UNROLL_SIZE ] = { 0 };
217- #ifdef NEED_SXX
218170 double Sxxarray [UNROLL_SIZE ] = { 0 };
219- #endif
220171
221172 size_t row = 0 ;
222173
223- #ifdef NEED_SXX
224174 /*
225175 * Initialize each state with the first matching row. We do this separately
226176 * to make the actual update function branchless, namely the computation of
@@ -251,7 +201,6 @@ FUNCTION_NAME(vector_impl)(void *agg_state, size_t n, const CTYPE *values, const
251201 {
252202 UPDATE (filter , values , row , & Narray [inner ], & Sxarray [inner ], & Sxxarray [inner ]);
253203 }
254- #endif
255204
256205 /*
257206 * Unrolled loop.
@@ -300,7 +249,6 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value)
300249 */
301250 const double newN = state -> N + 1.0 ;
302251 const double newSx = state -> Sx + value ;
303- #ifdef NEED_SXX
304252 if (state -> N > 0.0 )
305253 {
306254 const double tmp = value * newN - newSx ;
@@ -310,7 +258,6 @@ FUNCTION_NAME(one)(void *restrict agg_state, const CTYPE value)
310258 {
311259 state -> Sxx = 0 * value ;
312260 }
313- #endif
314261
315262 state -> N = newN ;
316263 state -> Sx = newSx ;
0 commit comments