@@ -17,10 +17,8 @@ typedef struct pc_qset
1717 pd_t uprice_ [PC_COMP_SIZE ];
1818 pd_t lprice_ [PC_COMP_SIZE ];
1919 pd_t weight_ [PC_COMP_SIZE ];
20- pd_t cumwgt_ [PC_COMP_SIZE ];
2120 int64_t decay_ [1 + PC_MAX_SEND_LATENCY ];
2221 int64_t fact_ [PC_FACTOR_SIZE ];
23- uint32_t num_ ;
2422 int32_t expo_ ;
2523} pc_qset_t ;
2624
@@ -78,7 +76,6 @@ static pc_qset_t *qset_new( int expo )
7876 qs -> fact_ [16 ] = 10000000000000000L ;
7977 qs -> fact_ [17 ] = 100000000000000000L ;
8078
81- qs -> num_ = 0 ;
8279 qs -> expo_ = expo ;
8380
8481 return qs ;
@@ -136,10 +133,25 @@ static inline void upd_twap(
136133}
137134
138135// compute weighted percentile
139- static void wgt_ptile ( pd_t * res , pd_t * prices , pd_t * ptile , pc_qset_t * qs )
136+ static void wgt_ptile (
137+ pd_t * const res
138+ , const pd_t * const prices , const pd_t * const weights , const uint32_t num
139+ , const pd_t * const ptile , pc_qset_t * qs )
140140{
141- pd_t * cumwgt = qs -> cumwgt_ ;
142- uint32_t i = 0 , num = qs -> num_ ;
141+ pd_t cumwgt [ PC_COMP_SIZE ];
142+
143+ pd_t cumwgta [ 1 ], half [ 1 ];
144+ pd_new ( cumwgta , 0 , 0 );
145+ pd_new ( half , 5 , -1 );
146+ for ( uint32_t i = 0 ; i < num ; ++ i ) {
147+ const pd_t * const wptr = & weights [ i ];
148+ pd_t weight [ 1 ];
149+ pd_mul ( weight , wptr , half );
150+ pd_add ( & cumwgt [ i ], cumwgta , weight , qs -> fact_ );
151+ pd_add ( cumwgta , cumwgta , wptr , qs -> fact_ );
152+ }
153+
154+ uint32_t i = 0 ;
143155 for ( ; i != num && pd_lt ( & cumwgt [i ], ptile , qs -> fact_ ); ++ i );
144156 if ( i == num ) {
145157 pd_set ( res , & prices [num - 1 ] );
@@ -254,7 +266,6 @@ static inline void upd_aggregate( pc_price_t *ptr, uint64_t slot )
254266 pd_new ( one , 100000000L , -8 );
255267 pd_new ( wsum , 0 , 0 );
256268 int64_t ldiff = INT64_MAX ;
257- qs -> num_ = numa ;
258269 pd_t * wptr = qs -> weight_ ;
259270 for ( uint32_t i = 0 ;i != numa ; ++ i ) {
260271 pc_price_comp_t * iptr = & ptr -> comp_ [aidx [i ]];
@@ -292,9 +303,10 @@ static inline void upd_aggregate( pc_price_t *ptr, uint64_t slot )
292303
293304 // bound weights at 1/sqrt(Nquotes) and redeistribute the remaining weight
294305 // among the remaining quoters proportional to their weights
295- pd_t wmax [1 ], rnumer [1 ], rdenom [1 ], half [ 1 ], cumwgt [ 1 ] ;
306+ pd_t wmax [1 ], rnumer [1 ], rdenom [1 ];
296307 pd_set ( rnumer , one );
297308 pd_new ( rdenom , 0 , 0 );
309+ // wmax = 1 / sqrt( numa )
298310 pd_new ( wmax , numa , 0 );
299311 pd_sqrt ( wmax , wmax , qs -> fact_ );
300312 pd_div ( wmax , one , wmax );
@@ -313,38 +325,58 @@ static inline void upd_aggregate( pc_price_t *ptr, uint64_t slot )
313325 if ( rdenom -> v_ ) {
314326 pd_div ( rnumer , rnumer , rdenom );
315327 }
316- pd_new ( cumwgt , 0 , 0 );
317- pd_new ( half , 5 , -1 );
318- for ( uint32_t i = 0 ;i != numa ; ++ i ) {
319- wptr = & qs -> weight_ [i ];
320- if ( aidx [i ] == 0 ) {
328+ for ( uint32_t i = 0 ; i != numa ; ++ i ) {
329+ wptr = & qs -> weight_ [ i ];
330+ if ( aidx [ i ] == 0 ) {
321331 pd_mul ( wptr , wptr , rnumer );
322332 }
323- pd_mul ( weight , wptr , half );
324- pd_add ( & qs -> cumwgt_ [i ], cumwgt , weight , qs -> fact_ );
325- pd_add ( cumwgt , cumwgt , wptr , qs -> fact_ );
326333 }
327334
335+ const pd_t half = { .e_ = -1 , .v_ = 5 };
336+
328337 // compute aggregate price as weighted median
329338 pd_t iprice [1 ], lprice [1 ], uprice [1 ], q3price [1 ], q1price [1 ], ptile [1 ];
330339 pd_new ( ptile , 5 , -1 );
331- wgt_ptile ( iprice , qs -> iprice_ , ptile , qs );
340+ wgt_ptile ( iprice , qs -> iprice_ , qs -> weight_ , numa , ptile , qs );
332341 pd_adjust ( iprice , ptr -> expo_ , qs -> fact_ );
333342 ptr -> agg_ .price_ = iprice -> v_ ;
334343
335344 // compute diff in weighted median between upper and lower price bounds
336- wgt_ptile ( uprice , qs -> uprice_ , ptile , qs );
337- wgt_ptile ( lprice , qs -> lprice_ , ptile , qs );
345+ pd_t prices [ PC_COMP_SIZE ];
346+ pd_t weights [ PC_COMP_SIZE ];
347+ // sort upper prices and weights
348+ for ( uint32_t i = 0 ; i < numa ; ++ i ) {
349+ uint32_t j = i ;
350+ for ( ; j > 0 && pd_lt ( & qs -> uprice_ [ i ], & prices [ j - 1 ], qs -> fact_ ); -- j ) {
351+ prices [ j ] = prices [ j - 1 ];
352+ weights [ j ] = weights [ j - 1 ];
353+ }
354+ prices [ j ] = qs -> uprice_ [ i ];
355+ weights [ j ] = qs -> weight_ [ i ];
356+ }
357+ wgt_ptile ( uprice , prices , weights , numa , ptile , qs );
358+ // sort lower prices and weights
359+ for ( uint32_t i = 0 ; i < numa ; ++ i ) {
360+ uint32_t j = i ;
361+ for ( ; j > 0 && pd_lt ( & qs -> lprice_ [ i ], & prices [ j - 1 ], qs -> fact_ ); -- j ) {
362+ prices [ j ] = prices [ j - 1 ];
363+ weights [ j ] = weights [ j - 1 ];
364+ }
365+ prices [ j ] = qs -> lprice_ [ i ];
366+ weights [ j ] = qs -> weight_ [ i ];
367+ }
368+ wgt_ptile ( lprice , prices , weights , numa , ptile , qs );
369+
338370 pd_sub ( uprice , uprice , lprice , qs -> fact_ );
339- pd_mul ( uprice , uprice , half );
371+ pd_mul ( uprice , uprice , & half );
340372
341373 // compute weighted iqr of prices
342374 pd_new ( ptile , 75 , -2 );
343- wgt_ptile ( q3price , qs -> iprice_ , ptile , qs );
375+ wgt_ptile ( q3price , qs -> iprice_ , qs -> weight_ , numa , ptile , qs );
344376 pd_new ( ptile , 25 , -2 );
345- wgt_ptile ( q1price , qs -> iprice_ , ptile , qs );
377+ wgt_ptile ( q1price , qs -> iprice_ , qs -> weight_ , numa , ptile , qs );
346378 pd_sub ( q3price , q3price , q1price , qs -> fact_ );
347- pd_mul ( q3price , q3price , half );
379+ pd_mul ( q3price , q3price , & half );
348380
349381 // take confidence interval as larger
350382 pd_t * cptr = pd_gt ( uprice , q3price , qs -> fact_ ) ? uprice : q3price ;
0 commit comments