Loading [MathJax]/extensions/TeX/AMSsymbols.js
LAL 7.7.0.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
LALRunningMedian.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Bernd Machenschalk, Jolien Creighton, Reinhard Prix
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20/* ---------- see LALRunningMedian.h for doxygen documentation ---------- */
21
22#include <stdio.h>
23#include <math.h>
24#include <lal/LALStdlib.h>
25#include <lal/AVFactories.h>
26#include <lal/LALRunningMedian.h>
27
28/*----------------------------------
29 A structure to store values and indices
30 of elements in an array
31 -----------------------------------*/
35};
39};
40
41
42static int rngmed_sortindex8(const void *elem1, const void *elem2){
43 /*Used in running qsort*/
44
45 const struct rngmed_val_index8 *A = elem1;
46 const struct rngmed_val_index8 *B = elem2;
47 REAL8 data1, data2;
48
49 data1=A->data;
50 data2=B->data;
51 if (data1 < data2)
52 return -1;
53 else if (data1==data2)
54 return 0;
55 else
56 return 1;
57}
58
59static int rngmed_sortindex4(const void *elem1, const void *elem2){
60 /*Used in running qsort*/
61
62 const struct rngmed_val_index4 *A = elem1;
63 const struct rngmed_val_index4 *B = elem2;
64 REAL4 data1, data2;
65
66 data1=A->data;
67 data2=B->data;
68 if (data1 < data2)
69 return -1;
70 else if (data1==data2)
71 return 0;
72 else
73 return 1;
74}
75
76
77/* Used in running qsort, RunningMedian2 version */
78static int rngmed_qsortindex8(const void *elem1, const void *elem2){
79 struct qsnode{
80 REAL8 value;
81 UINT4 index;
82 };
83
84 const struct qsnode *A = elem1;
85 const struct qsnode *B = elem2;
86
87 if (B->value > A->value)
88 return -1;
89 else if (A->value > B->value)
90 return 1;
91 else if (A->index > B->index)
92 return -1;
93 else
94 return 1;
95}
96
97/* Used in running qsort, RunningMedian2 version */
98static int rngmed_qsortindex4(const void *elem1, const void *elem2){
99 struct qsnode{
100 REAL4 value;
101 UINT4 index;
102 };
103
104 const struct qsnode *A = elem1;
105 const struct qsnode *B = elem2;
106
107 if (B->value > A->value)
108 return -1;
109 else if (A->value > B->value)
110 return 1;
111 else if (A->index > B->index)
112 return -1;
113 else
114 return 1;
115}
116
117
119 REAL8Sequence *medians,
120 const REAL8Sequence *input,
122
123{
124 /*----------------------------------
125 Two types of pointers:
126 (a)next_sorted: point to the next node in sorted list
127 (b)next_sequence: point to the next node in sequential list
128 ------------------------------------*/
129 struct node{
130 REAL8 data;
131 struct node *next_sorted, *next_sequence, *prev_sorted;
132 int rank; /*Used for constructing optional output*/
133 };
134
135 /*----------------------------------
136 checks: Array to hold pointers to Checkpoint nodes.
137 first_sequence: Pointer to first node of sequential list
138 ------------------------------------*/
139 struct node **checks = NULL;
140 struct node **node_addresses = NULL;
141 struct node *first_sequence = NULL;
142 struct node *last_sequence = NULL;
143 struct node *currentnode = NULL;
144 struct node *previousnode = NULL;
145 struct node *leftnode = NULL;
146 struct node *rightnode = NULL;
147 struct node *reuse_next_sorted = NULL;
148 struct node *reuse_prev_sorted = NULL;
149 struct node *dummy_node = NULL;
150 struct node *dummy_node1 = NULL;
151 struct node *dummy_node2 = NULL;
152 UINT4 ncheckpts,stepchkpts;
153 UINT4 nextchkptindx,*checks4shift;
154 UINT4 nearestchk,midpoint,offset,numberoffsets;
155 UINT4 samplecount,counter_chkpt,chkcount=0, shiftcounter=0;
156 INT8 k;
157 REAL8 nextsample,deletesample,dummy;
158 INT4 shift,dummy_int;
159 /* for initial qsort */
160 REAL8 *sorted_indices;
161 struct rngmed_val_index8 *index_block;
162
164
165 /* check input parameters */
166 /* input must not be NULL */
167 ASSERT(input,status,LALRUNNINGMEDIANH_ENULL,LALRUNNINGMEDIANH_MSGENULL);
168 /* param.blocksize must be >2 */
169 ASSERT(param.blocksize>2,status,LALRUNNINGMEDIANH_EZERO,LALRUNNINGMEDIANH_MSGEZERO);
170 /* blocksize must not be larger than input size */
171 ASSERT(param.blocksize <= input->length,status,LALRUNNINGMEDIANH_ELARGE,LALRUNNINGMEDIANH_MSGELARGE);
172 /* medians must point to a valid sequence of correct size */
173 ASSERT(medians,status,LALRUNNINGMEDIANH_EIMED,LALRUNNINGMEDIANH_MSGEIMED);
174 ASSERT(medians->length == (input->length - param.blocksize + 1),status,LALRUNNINGMEDIANH_EIMED,LALRUNNINGMEDIANH_MSGEIMED);
175
177
178 /*-----------------------------------
179 Sort the first block of param.blocksize samples
180 ------------------------------------*/
181 index_block =(struct rngmed_val_index8 *)LALCalloc(param.blocksize, sizeof(struct rngmed_val_index8));
182 if(!index_block) {
183 ABORT(status,LALRUNNINGMEDIANH_EMALOC1,LALRUNNINGMEDIANH_MSGEMALOC1);
184 }
185 for(k=0;k<param.blocksize;k++){
186 index_block[k].data=input->data[k];
187 index_block[k].index=k;
188 }
189
190 qsort(index_block, param.blocksize, sizeof(struct rngmed_val_index8),rngmed_sortindex8);
191
192 sorted_indices=(REAL8 *)LALCalloc(param.blocksize,sizeof(REAL8));
193 if(!sorted_indices) {
194 LALFree(index_block);
195 ABORT(status,LALRUNNINGMEDIANH_EMALOC1,LALRUNNINGMEDIANH_MSGEMALOC1);
196 }
197
198 for(k=0;k<param.blocksize;k++){
199 sorted_indices[k]=index_block[k].index;
200 }
201
202 LALFree(index_block);
203
204 /*----------------------------------
205 Indices of checkpoint nodes.
206 Number of nodes per checkpoint=floor(sqrt(param.blocksize))
207 ------------------------------------*/
208 stepchkpts = sqrt(param.blocksize);
209 ncheckpts = param.blocksize/stepchkpts;
210 checks = (struct node **)LALCalloc(ncheckpts,sizeof(struct node*));
211 if(!checks){
212 LALFree(sorted_indices);
213 ABORT(status,LALRUNNINGMEDIANH_EMALOC2,LALRUNNINGMEDIANH_MSGEMALOC2);
214 }
215 checks4shift = LALCalloc(ncheckpts,sizeof(INT4));
216 if(!checks4shift){
217 LALFree(sorted_indices);
218 LALFree(checks);
219 ABORT(status,LALRUNNINGMEDIANH_EMALOC3,LALRUNNINGMEDIANH_MSGEMALOC3);
220 }
221
222 /*---------------------------------
223 Offsets for getting median from nearest
224 checkpoint: For param.blocksize even,
225 (node(offset(1))+node(offset(2)))/2;
226 for param.blocksize odd,
227 (node(offset(1))+node(offset(1)))/2;
228 ----------------------------------*/
229 if((int)fmod(param.blocksize,2.0)){
230 /*Odd*/
231 midpoint=(param.blocksize+1)/2-1;
232 numberoffsets=1;
233 }
234 else{
235 /*Even*/
236 midpoint=param.blocksize/2-1;
237 numberoffsets=2;
238 }
239 nearestchk=floor(midpoint/stepchkpts);
240 offset=midpoint-nearestchk*stepchkpts;
241
242 /*----------------------------------
243 Build up linked list using first nblock points
244 in sequential order
245 ------------------------------------*/
246 node_addresses=(struct node **)LALCalloc(param.blocksize,sizeof(struct node *));
247 if(!node_addresses){
248 LALFree(sorted_indices);
249 LALFree(checks4shift);
250 LALFree(checks);
251 ABORT(status,LALRUNNINGMEDIANH_EMALOC4,LALRUNNINGMEDIANH_MSGEMALOC4);
252 }
253 first_sequence=(struct node *)LALCalloc(1,sizeof(struct node));
254 if(!first_sequence){
255 LALFree(node_addresses);
256 LALFree(sorted_indices);
257 LALFree(checks4shift);
258 LALFree(checks);
259 ABORT(status,LALRUNNINGMEDIANH_EMALOC5,LALRUNNINGMEDIANH_MSGEMALOC5);
260 }
261 node_addresses[0]=first_sequence;
262 first_sequence->next_sequence=NULL;
263 first_sequence->next_sorted=NULL;
264 first_sequence->prev_sorted=NULL;
265 first_sequence->data=input->data[0];
266 previousnode=first_sequence;
267 for(samplecount=1;samplecount<param.blocksize;samplecount++){
268 currentnode=(struct node *)LALCalloc(1,sizeof(struct node));
269 if(!currentnode){
270 LALFree(first_sequence);
271 LALFree(sorted_indices);
272 LALFree(node_addresses);
273 LALFree(checks4shift);
274 LALFree(checks);
275 ABORT(status,LALRUNNINGMEDIANH_EMALOC6,LALRUNNINGMEDIANH_MSGEMALOC6);
276 }
277 node_addresses[samplecount]=currentnode;
278 previousnode->next_sequence=currentnode;
279 currentnode->next_sequence=NULL;
280 currentnode->prev_sorted=NULL;
281 currentnode->next_sorted=NULL;
282 currentnode->data=input->data[samplecount];
283 previousnode=currentnode;
284 }
285 last_sequence=currentnode;
286
287 /*------------------------------------
288 Set the sorted sequence pointers and
289 the pointers to checkpoint nodes
290 -------------------------------------*/
291 currentnode=node_addresses[(int)sorted_indices[0]];
292 previousnode=NULL;
293 checks[0]=currentnode;
294 nextchkptindx=stepchkpts;
295 counter_chkpt=1;
296 for(samplecount=1;samplecount<param.blocksize;samplecount++){
297 dummy_node=node_addresses[(int)sorted_indices[samplecount]];
298 currentnode->next_sorted=dummy_node;
299 currentnode->prev_sorted=previousnode;
300 previousnode=currentnode;
301 currentnode=dummy_node;
302 if(samplecount==nextchkptindx && counter_chkpt<ncheckpts){
303 checks[counter_chkpt]=currentnode;
304 nextchkptindx+=stepchkpts;
305 counter_chkpt++;
306 }
307 }
308 currentnode->prev_sorted=previousnode;
309 currentnode->next_sorted=NULL;
310 LALFree(sorted_indices);
311
312 /*------------------------------
313 get the first output element
314 -------------------------------*/
315 currentnode=checks[nearestchk];
316 for(k=1;k<=offset;k++){
317 currentnode=currentnode->next_sorted;
318 }
319 dummy=0;
320 for(k=1;k<=numberoffsets;k++){
321 dummy+=currentnode->data;
322 currentnode=currentnode->next_sorted;
323 }
324 medians->data[0]=dummy/numberoffsets;
325
326 /*---------------------------------
327 This is the main part
328 ----------------------------------*/
329 for(samplecount=param.blocksize;samplecount<input->length;samplecount++){
330 nextsample=input->data[samplecount];
331 if(nextsample>=checks[0]->data){ /* corrected */
332 for(chkcount=1;chkcount<ncheckpts;chkcount++){
333 if(nextsample>checks[chkcount]->data){
334 }
335 else{
336 break;
337 }
338 }
339 chkcount-=1;
340 rightnode=checks[chkcount];
341 leftnode=NULL; /* corrected */
342 while(rightnode){
343 if(nextsample<rightnode->data){ /* corrected */
344 break;
345 }
346 leftnode=rightnode;
347 rightnode=rightnode->next_sorted;
348 }
349 } else {
350 /* corrected */
351 /* new case */
352 if(nextsample<checks[0]->data){
353 chkcount=0;
354 /* dummy_node=checks[0]; */
355 rightnode=checks[0];
356 leftnode=NULL;
357 }
358 }
359
360 /* corrected */
361 /* from here ... */
362 dummy_node=NULL;
363 if(rightnode==first_sequence){
364 dummy_node=rightnode;
365 }
366 else if(leftnode==first_sequence){
367 dummy_node=leftnode;
368 }
369 if(dummy_node) {
370 dummy_node->data=nextsample;
371 first_sequence=first_sequence->next_sequence;
372 dummy_node->next_sequence=NULL;
373 last_sequence->next_sequence=dummy_node;
374 last_sequence=dummy_node;
375 shift=0;
376 }
377 else{
378 reuse_next_sorted=rightnode;
379 reuse_prev_sorted=leftnode;
380 shift=1; /*shift maybe required*/
381 }
382 /* to here */
383
384 /*-----------------------------------
385 Getting check points to be shifted
386 -----------------------------------*/
387 if(shift){
388 deletesample=first_sequence->data;
389 if(deletesample>nextsample){
390 shiftcounter=0;
391 for(k=chkcount;k<ncheckpts;k++){
392 dummy=checks[k]->data;
393 if(dummy>nextsample){ /* corrected */
394 if(dummy<=deletesample){
395 checks4shift[shiftcounter]=k;
396 shiftcounter++;
397 }
398 else{
399 break;
400 }
401 }
402 }
403 shift=-1; /*Left shift*/
404 }
405 else
406 if(deletesample<nextsample){
407 shiftcounter=0;
408 for(k=chkcount;k>=0;k--){
409 dummy=checks[k]->data;
410 if(dummy>=deletesample){
411 checks4shift[shiftcounter]=k;
412 shiftcounter++;
413 }
414 else{
415 break;
416 }
417 }
418 shift=1; /*Shift Right*/
419 }
420 /* corrected: else case deleted */
421 }
422
423 /*------------------------------
424 Delete and Insert
425 --------------------------------*/
426 if(shift){
427 dummy_node=first_sequence;
428 first_sequence=dummy_node->next_sequence;
429 dummy_node->next_sequence=NULL;
430 last_sequence->next_sequence=dummy_node;
431 last_sequence=dummy_node;
432 dummy_node->data=nextsample;
433 dummy_node1=dummy_node->prev_sorted;
434 dummy_node2=dummy_node->next_sorted;
435
436 /*-----------------------
437 Repair deletion point
438 ------------------------*/
439 if(!dummy_node1){
440 dummy_node2->prev_sorted=dummy_node1;
441 }
442 else {
443 if(!dummy_node2){
444 dummy_node1->next_sorted=dummy_node2;
445 }
446 else{
447 dummy_node1->next_sorted=dummy_node2;
448 dummy_node2->prev_sorted=dummy_node1;
449 }
450 }
451
452 /*------------------------
453 Set pointers from neighbours to new node at insertion point
454 -------------------------*/
455 if(!rightnode){
456 leftnode->next_sorted=dummy_node;
457 }
458 else {
459 if(!leftnode){
460 rightnode->prev_sorted=dummy_node;
461 }
462 else{
463 leftnode->next_sorted=dummy_node;
464 rightnode->prev_sorted=dummy_node;
465 }
466 }
467
468 /*-------------------------------
469 Shift check points before resetting sorted list
470 --------------------------------*/
471 if(shift==-1){
472 for(k=0;k<shiftcounter;k++){
473 dummy_int=checks4shift[k];
474 checks[dummy_int]=checks[dummy_int]->prev_sorted;
475 }
476 }
477 else
478 if(shift==1){
479 for(k=0;k<shiftcounter;k++){
480 dummy_int=checks4shift[k];
481 checks[dummy_int]=checks[dummy_int]->next_sorted;
482 }
483 }
484
485 /*--------------------------------
486 insert node
487 --------------------------------*/
488 dummy_node->next_sorted=reuse_next_sorted;
489 dummy_node->prev_sorted=reuse_prev_sorted;
490 }
491
492 /*--------------------------------
493 Get the median
494 ---------------------------------*/
495 currentnode=checks[nearestchk];
496 for(k=1;k<=offset;k++){
497 currentnode=currentnode->next_sorted;
498 }
499 dummy=0;
500 for(k=1;k<=numberoffsets;k++){
501 dummy+=currentnode->data;
502 currentnode=currentnode->next_sorted;
503 }
504 medians->data[samplecount-param.blocksize+1]=dummy/numberoffsets;
505 }/*Outer For Loop*/
506
507
508 /*--------------------------------
509 Clean Up
510 ---------------------------------*/
511 LALFree(node_addresses);
512 currentnode=first_sequence;
513 while(currentnode){
514 previousnode=currentnode;
515 currentnode=currentnode->next_sequence;
516 LALFree(previousnode);
517 }
518 LALFree(checks4shift);
519 LALFree(checks);
520
522 RETURN( status );
523}
524
525
527 REAL4Sequence *medians,
528 const REAL4Sequence *input,
530
531{
532 /*----------------------------------
533 Two types of pointers:
534 (a)next_sorted: point to the next node in sorted list
535 (b)next_sequence: point to the next node in sequential list
536 ------------------------------------*/
537 struct node{
538 REAL4 data;
539 struct node *next_sorted, *next_sequence, *prev_sorted;
540 int rank; /*Used for constructing optional output*/
541 };
542
543 /*----------------------------------
544 checks: Array to hold pointers to Checkpoint nodes.
545 first_sequence: Pointer to first node of sequential list
546 ------------------------------------*/
547 struct node **checks = NULL;
548 struct node **node_addresses = NULL;
549 struct node *first_sequence = NULL;
550 struct node *last_sequence = NULL;
551 struct node *currentnode = NULL;
552 struct node *previousnode = NULL;
553 struct node *leftnode = NULL;
554 struct node *rightnode = NULL;
555 struct node *reuse_next_sorted = NULL;
556 struct node *reuse_prev_sorted = NULL;
557 struct node *dummy_node = NULL;
558 struct node *dummy_node1 = NULL;
559 struct node *dummy_node2 = NULL;
560 UINT4 ncheckpts,stepchkpts;
561 UINT4 nextchkptindx,*checks4shift;
562 UINT4 nearestchk,midpoint,offset,numberoffsets;
563 UINT4 samplecount,counter_chkpt,chkcount=0,shiftcounter=0;
564 INT8 k;
565 REAL4 nextsample,deletesample,dummy;
566 INT4 shift,dummy_int;
567 /* for initial qsort */
568 REAL4 *sorted_indices;
569 struct rngmed_val_index4 *index_block;
570
571
573
574 /* check input parameters */
575 /* input must not be NULL */
576 ASSERT(input,status,LALRUNNINGMEDIANH_ENULL,LALRUNNINGMEDIANH_MSGENULL);
577 /* param.blocksize must be >2 */
578 ASSERT(param.blocksize>2,status,LALRUNNINGMEDIANH_EZERO,LALRUNNINGMEDIANH_MSGEZERO);
579 /* param.blocksize must not be larger than input size */
580 ASSERT(param.blocksize <= input->length,status,LALRUNNINGMEDIANH_ELARGE,LALRUNNINGMEDIANH_MSGELARGE);
581 /* medians must point to a valid sequence of correct size */
582 ASSERT(medians,status,LALRUNNINGMEDIANH_EIMED,LALRUNNINGMEDIANH_MSGEIMED);
583 ASSERT(medians->length == (input->length - param.blocksize + 1),status,LALRUNNINGMEDIANH_EIMED,LALRUNNINGMEDIANH_MSGEIMED);
584
586
587 /*-----------------------------------
588 Sort the first block of param.blocksize samples
589 ------------------------------------*/
590 index_block =(struct rngmed_val_index4 *)LALCalloc(param.blocksize, sizeof(struct rngmed_val_index4));
591 if(!index_block) {
592 ABORT(status,LALRUNNINGMEDIANH_EMALOC1,LALRUNNINGMEDIANH_MSGEMALOC1);
593 }
594 for(k=0;k<param.blocksize;k++){
595 index_block[k].data=input->data[k];
596 index_block[k].index=k;
597 }
598
599 qsort(index_block, param.blocksize, sizeof(struct rngmed_val_index4),rngmed_sortindex4);
600
601 sorted_indices=(REAL4 *)LALCalloc(param.blocksize,sizeof(REAL4));
602 if(!sorted_indices) {
603 LALFree(index_block);
604 ABORT(status,LALRUNNINGMEDIANH_EMALOC1,LALRUNNINGMEDIANH_MSGEMALOC1);
605 }
606
607 for(k=0;k<param.blocksize;k++){
608 sorted_indices[k]=index_block[k].index;
609 }
610
611 LALFree(index_block);
612
613 /*----------------------------------
614 Indices of checkpoint nodes.
615 Number of nodes per checkpoint=floor(sqrt(param.blocksize))
616 ------------------------------------*/
617 stepchkpts = sqrt(param.blocksize);
618 ncheckpts = param.blocksize/stepchkpts;
619 checks = (struct node **)LALCalloc(ncheckpts,sizeof(struct node*));
620 if(!checks){
621 LALFree(sorted_indices);
622 ABORT(status,LALRUNNINGMEDIANH_EMALOC2,LALRUNNINGMEDIANH_MSGEMALOC2);
623 }
624 checks4shift = LALCalloc(ncheckpts,sizeof(INT4));
625 if(!checks4shift){
626 LALFree(sorted_indices);
627 LALFree(checks);
628 ABORT(status,LALRUNNINGMEDIANH_EMALOC3,LALRUNNINGMEDIANH_MSGEMALOC3);
629 }
630
631 /*---------------------------------
632 Offsets for getting median from nearest
633 checkpoint: For param.blocksize even,
634 (node(offset(1))+node(offset(2)))/2;
635 for param.blocksize odd,
636 (node(offset(1))+node(offset(1)))/2;
637 ----------------------------------*/
638 if((int)fmod(param.blocksize,2.0)){
639 /*Odd*/
640 midpoint=(param.blocksize+1)/2-1;
641 numberoffsets=1;
642 }
643 else{
644 /*Even*/
645 midpoint=param.blocksize/2-1;
646 numberoffsets=2;
647 }
648 nearestchk=floor(midpoint/stepchkpts);
649 offset=midpoint-nearestchk*stepchkpts;
650
651 /*----------------------------------
652 Build up linked list using first nblock points
653 in sequential order
654 ------------------------------------*/
655 node_addresses=(struct node **)LALCalloc(param.blocksize,sizeof(struct node *));
656 if(!node_addresses){
657 LALFree(sorted_indices);
658 LALFree(checks4shift);
659 LALFree(checks);
660 ABORT(status,LALRUNNINGMEDIANH_EMALOC4,LALRUNNINGMEDIANH_MSGEMALOC4);
661 }
662 first_sequence=(struct node *)LALCalloc(1,sizeof(struct node));
663 if(!first_sequence){
664 LALFree(node_addresses);
665 LALFree(sorted_indices);
666 LALFree(checks4shift);
667 LALFree(checks);
668 ABORT(status,LALRUNNINGMEDIANH_EMALOC5,LALRUNNINGMEDIANH_MSGEMALOC5);
669 }
670 node_addresses[0]=first_sequence;
671 first_sequence->next_sequence=NULL;
672 first_sequence->next_sorted=NULL;
673 first_sequence->prev_sorted=NULL;
674 first_sequence->data=input->data[0];
675 previousnode=first_sequence;
676 for(samplecount=1;samplecount<param.blocksize;samplecount++){
677 currentnode=(struct node *)LALCalloc(1,sizeof(struct node));
678 if(!currentnode){
679 LALFree(first_sequence);
680 LALFree(sorted_indices);
681 LALFree(node_addresses);
682 LALFree(checks4shift);
683 LALFree(checks);
684 ABORT(status,LALRUNNINGMEDIANH_EMALOC6,LALRUNNINGMEDIANH_MSGEMALOC6);
685 }
686 node_addresses[samplecount]=currentnode;
687 previousnode->next_sequence=currentnode;
688 currentnode->next_sequence=NULL;
689 currentnode->prev_sorted=NULL;
690 currentnode->next_sorted=NULL;
691 currentnode->data=input->data[samplecount];
692 previousnode=currentnode;
693 }
694 last_sequence=currentnode;
695
696 /*------------------------------------
697 Set the sorted sequence pointers and
698 the pointers to checkpoint nodes
699 -------------------------------------*/
700 currentnode=node_addresses[(int)sorted_indices[0]];
701 previousnode=NULL;
702 checks[0]=currentnode;
703 nextchkptindx=stepchkpts;
704 counter_chkpt=1;
705 for(samplecount=1;samplecount<param.blocksize;samplecount++){
706 dummy_node=node_addresses[(int)sorted_indices[samplecount]];
707 currentnode->next_sorted=dummy_node;
708 currentnode->prev_sorted=previousnode;
709 previousnode=currentnode;
710 currentnode=dummy_node;
711 if(samplecount==nextchkptindx && counter_chkpt<ncheckpts){
712 checks[counter_chkpt]=currentnode;
713 nextchkptindx+=stepchkpts;
714 counter_chkpt++;
715 }
716 }
717 currentnode->prev_sorted=previousnode;
718 currentnode->next_sorted=NULL;
719 LALFree(sorted_indices);
720
721 /*------------------------------
722 get the first output element
723 -------------------------------*/
724 currentnode=checks[nearestchk];
725 for(k=1;k<=offset;k++){
726 currentnode=currentnode->next_sorted;
727 }
728 dummy=0;
729 for(k=1;k<=numberoffsets;k++){
730 dummy+=currentnode->data;
731 currentnode=currentnode->next_sorted;
732 }
733 medians->data[0]=dummy/numberoffsets;
734
735 /*---------------------------------
736 This is the main part
737 ----------------------------------*/
738 for(samplecount=param.blocksize;samplecount<input->length;samplecount++){
739 nextsample=input->data[samplecount];
740 if(nextsample>=checks[0]->data){ /* corrected */
741 for(chkcount=1;chkcount<ncheckpts;chkcount++){
742 if(nextsample>checks[chkcount]->data){
743 }
744 else{
745 break;
746 }
747 }
748 chkcount-=1;
749 rightnode=checks[chkcount];
750 leftnode=NULL; /* corrected */
751 while(rightnode){
752 if(nextsample<rightnode->data){ /* corrected */
753 break;
754 }
755 leftnode=rightnode;
756 rightnode=rightnode->next_sorted;
757 }
758 } else {
759 /* corrected */
760 /* new case */
761 if(nextsample<checks[0]->data){
762 chkcount=0;
763 /* dummy_node=checks[0]; */
764 rightnode=checks[0];
765 leftnode=NULL;
766 }
767 }
768
769 /* corrected */
770 /* from here ... */
771 dummy_node=NULL;
772 if(rightnode==first_sequence){
773 dummy_node=rightnode;
774 }
775 else if(leftnode==first_sequence){
776 dummy_node=leftnode;
777 }
778 if(dummy_node) {
779 dummy_node->data=nextsample;
780 first_sequence=first_sequence->next_sequence;
781 dummy_node->next_sequence=NULL;
782 last_sequence->next_sequence=dummy_node;
783 last_sequence=dummy_node;
784 shift=0;
785 }
786 else{
787 reuse_next_sorted=rightnode;
788 reuse_prev_sorted=leftnode;
789 shift=1; /*shift maybe required*/
790 }
791 /* to here */
792
793 /*-----------------------------------
794 Getting check points to be shifted
795 -----------------------------------*/
796 if(shift){
797 deletesample=first_sequence->data;
798 if(deletesample>nextsample){
799 shiftcounter=0;
800 for(k=chkcount;k<ncheckpts;k++){
801 dummy=checks[k]->data;
802 if(dummy>nextsample){ /* corrected */
803 if(dummy<=deletesample){
804 checks4shift[shiftcounter]=k;
805 shiftcounter++;
806 }
807 else{
808 break;
809 }
810 }
811 }
812 shift=-1; /*Left shift*/
813 }
814 else
815 if(deletesample<nextsample){
816 shiftcounter=0;
817 for(k=chkcount;k>=0;k--){
818 dummy=checks[k]->data;
819 if(dummy>=deletesample){
820 checks4shift[shiftcounter]=k;
821 shiftcounter++;
822 }
823 else{
824 break;
825 }
826 }
827 shift=1; /*Shift Right*/
828 }
829 /* corrected: else case deleted */
830 }
831
832 /*------------------------------
833 Delete and Insert
834 --------------------------------*/
835 if(shift){
836 dummy_node=first_sequence;
837 first_sequence=dummy_node->next_sequence;
838 dummy_node->next_sequence=NULL;
839 last_sequence->next_sequence=dummy_node;
840 last_sequence=dummy_node;
841 dummy_node->data=nextsample;
842 dummy_node1=dummy_node->prev_sorted;
843 dummy_node2=dummy_node->next_sorted;
844
845 /*-----------------------
846 Repair deletion point
847 ------------------------*/
848 if(!dummy_node1){
849 dummy_node2->prev_sorted=dummy_node1;
850 }
851 else {
852 if(!dummy_node2){
853 dummy_node1->next_sorted=dummy_node2;
854 }
855 else{
856 dummy_node1->next_sorted=dummy_node2;
857 dummy_node2->prev_sorted=dummy_node1;
858 }
859 }
860
861 /*------------------------
862 Set pointers from neighbours to new node at insertion point
863 -------------------------*/
864 if(!rightnode){
865 leftnode->next_sorted=dummy_node;
866 }
867 else {
868 if(!leftnode){
869 rightnode->prev_sorted=dummy_node;
870 }
871 else{
872 leftnode->next_sorted=dummy_node;
873 rightnode->prev_sorted=dummy_node;
874 }
875 }
876
877 /*-------------------------------
878 Shift check points before resetting sorted list
879 --------------------------------*/
880 if(shift==-1){
881 for(k=0;k<shiftcounter;k++){
882 dummy_int=checks4shift[k];
883 checks[dummy_int]=checks[dummy_int]->prev_sorted;
884 }
885 }
886 else
887 if(shift==1){
888 for(k=0;k<shiftcounter;k++){
889 dummy_int=checks4shift[k];
890 checks[dummy_int]=checks[dummy_int]->next_sorted;
891 }
892 }
893
894 /*--------------------------------
895 insert node
896 --------------------------------*/
897 dummy_node->next_sorted=reuse_next_sorted;
898 dummy_node->prev_sorted=reuse_prev_sorted;
899 }
900
901 /*--------------------------------
902 Get the median
903 ---------------------------------*/
904 currentnode=checks[nearestchk];
905 for(k=1;k<=offset;k++){
906 currentnode=currentnode->next_sorted;
907 }
908 dummy=0;
909 for(k=1;k<=numberoffsets;k++){
910 dummy+=currentnode->data;
911 currentnode=currentnode->next_sorted;
912 }
913 medians->data[samplecount-param.blocksize+1]=dummy/numberoffsets;
914 }/*Outer For Loop*/
915
916
917 /*--------------------------------
918 Clean Up
919 ---------------------------------*/
920 LALFree(node_addresses);
921 currentnode=first_sequence;
922 while(currentnode){
923 previousnode=currentnode;
924 currentnode=currentnode->next_sequence;
925 LALFree(previousnode);
926 }
927 LALFree(checks4shift);
928 LALFree(checks);
929
931 RETURN( status );
932}
933
934
935
937 REAL8Sequence *medians,
938 const REAL8Sequence *input,
940
941{
942 /* a single "node"
943 lesser points to the next node with less or equal value
944 greater points to the next node with greater or equal value
945 an index == blocksize is an end marker
946 */
947 struct node{
948 REAL8 value;
949 UINT4 lesser;
950 UINT4 greater;
951 };
952
953 /* a node of the quicksort array */
954 struct qsnode{
955 REAL8 value;
956 UINT4 index;
957 };
958
959 const UINT4 bsize = param.blocksize; /* just an abbrevation */
960 const UINT4 nil = bsize; /* invalid index used as end marker */
961 const BOOLEAN isodd = bsize&1; /* bsize is odd = median is a single element */
962
963 struct node* nodes; /* array of nodes, will be of size blocksize */
964 struct qsnode* qsnodes; /* array of indices for initial qsort */
965 UINT4* checkpts; /* array of checkpoints */
966 UINT4 ncheckpts,stepchkpts; /* checkpoints: number and distance between */
967 UINT4 oldestnode; /* index of "oldest" node */
968 UINT4 i; /* loop counter (up to input length) */
969 INT4 j; /* loop counter (might get negative) */
970 UINT4 nmedian; /* current median, outer loop counter */
971 UINT4 midpoint; /* index of middle node in sorting order */
972 UINT4 mdnnearest; /* checkpoint "nearest" to the median */
973 UINT4 nextnode; /* node after an insertion point,
974 also used to find a median */
975 UINT4 prevnode; /* node before an insertion point */
976 UINT4 rightcheckpt; /* checkpoint 'right' of an insertion point */
977 REAL8 oldvalue,newvalue; /* old + new value of the node being replaced */
978 UINT4 oldlesser,oldgreater; /* remember the pointers of the replaced node */
979
981
982 /* check input parameters */
983 /* input must not be NULL */
984 ASSERT(input,status,LALRUNNINGMEDIANH_ENULL,LALRUNNINGMEDIANH_MSGENULL);
985 /* param.blocksize must be >2 */
986 ASSERT(param.blocksize>2,
987 status,LALRUNNINGMEDIANH_EZERO,LALRUNNINGMEDIANH_MSGEZERO);
988 /* blocksize must not be larger than input size */
989 ASSERT(param.blocksize <= input->length,
990 status,LALRUNNINGMEDIANH_ELARGE,LALRUNNINGMEDIANH_MSGELARGE);
991 /* medians must point to a valid sequence of correct size */
992 ASSERT(medians,status,LALRUNNINGMEDIANH_EIMED,LALRUNNINGMEDIANH_MSGEIMED);
993 ASSERT(medians->length == (input->length - param.blocksize + 1),
994 status,LALRUNNINGMEDIANH_EIMED,LALRUNNINGMEDIANH_MSGEIMED);
995
997
998 /* create nodes array */
999 nodes = (struct node*)LALCalloc(bsize, sizeof(struct node));
1000
1001 /* determine checkpoint positions */
1002 stepchkpts = sqrt(bsize);
1003 /* the old form
1004 ncheckpts = bsize/stepchkpts;
1005 caused too less checkpoints at the end, leading to break the
1006 cost calculation */
1007 ncheckpts = ceil((REAL4)bsize/(REAL4)stepchkpts);
1008
1009 /* set checkpoint nearest to the median and offset of the median to it */
1010 midpoint = (bsize+(bsize&1)) / 2 - 1;
1011 /* this becomes the median checkpoint */
1012 mdnnearest = ceil((REAL4)midpoint / (REAL4)stepchkpts);
1013
1014 /* add a checkpoint for the median if necessary */
1015 if (ceil((REAL4)midpoint / (REAL4)stepchkpts) != (REAL4)midpoint / (REAL4)stepchkpts)
1016 ncheckpts++;
1017
1018 /* create checkpoints array */
1019 checkpts = (UINT4*)LALCalloc(ncheckpts,sizeof(UINT4));
1020
1021 /* create array for qsort */
1022 qsnodes = (struct qsnode*)LALCalloc(bsize, sizeof(struct qsnode));
1023
1024 /* init qsort array
1025 the nodes get their values from the input,
1026 the indices are only identities qi[0]=0,qi[1]=1,... */
1027 for(i=0;i<bsize;i++) {
1028 qsnodes[i].value = input->data[i];
1029 qsnodes[i].index = i;
1030 }
1031
1032 /* sort qsnodes by value and index(!) */
1033 qsort(qsnodes, bsize, sizeof(struct qsnode),rngmed_qsortindex8);
1034
1035 /* init nodes array */
1036 for(i=0;i<bsize;i++)
1037 nodes[i].value = input->data[i];
1038 for(i=1;i<bsize-1;i++) {
1039 nodes[qsnodes[i-1].index].greater = qsnodes[i].index;
1040 nodes[qsnodes[i+1].index].lesser = qsnodes[i].index;
1041 }
1042 nodes[qsnodes[0].index].lesser = nil; /* end marker */
1043 nodes[qsnodes[1].index].lesser = qsnodes[0].index;
1044 nodes[qsnodes[bsize-2].index].greater = qsnodes[bsize-1].index;
1045 nodes[qsnodes[bsize-1].index].greater = nil; /* end marker */
1046
1047 /* setup checkpoints */
1048 /* j is the current checkpoint
1049 i is the stepping
1050 they are out of sync after a median checkpoint has been added */
1051 for(i=0,j=0; (UINT4)j<ncheckpts; i++,j++) {
1052 if ((UINT4)j == mdnnearest) {
1053 checkpts[j] = qsnodes[midpoint].index;
1054 if (i*stepchkpts != midpoint)
1055 j++;
1056 }
1057 checkpts[j] = qsnodes[i*stepchkpts].index;
1058 }
1059
1060 /* don't need the qsnodes anymore */
1061 LALFree(qsnodes);
1062
1063 /* find first median */
1064 nextnode = checkpts[mdnnearest];
1065 if(isodd)
1066 medians->data[0] = nodes[nextnode].value;
1067 else
1068 medians->data[0] = (nodes[nextnode].value
1069 + nodes[nodes[nextnode].greater].value) / 2.0;
1070
1071 /* the "oldest" node (first in sequence) is the one with index 0 */
1072 oldestnode = 0;
1073
1074 /* outer loop: find a median with each iteration */
1075 for(nmedian=1; nmedian < medians->length; nmedian++) {
1076
1077 /* remember value of sample to be deleted */
1078 oldvalue = nodes[oldestnode].value;
1079
1080 /* get next value to be inserted from input */
1081 newvalue = input->data[nmedian+bsize-1];
1082
1083 /** find point of insertion: **/
1084
1085 /* find checkpoint greater or equal newvalue */
1086 /* possible optimisation: use bisectional search instaed of linear */
1087 for(rightcheckpt=0; rightcheckpt<ncheckpts; rightcheckpt++)
1088 if(newvalue <= nodes[checkpts[rightcheckpt]].value)
1089 break;
1090
1091 /* assume we are inserting at the beginning: */
1092 prevnode = nil;
1093 if (rightcheckpt == 0)
1094 /* yes, we are */
1095 nextnode = checkpts[0];
1096 else {
1097 /* we're beyond the first checkpoint, find the node we're inserting at: */
1098 nextnode = checkpts[rightcheckpt-1]; /* this also works if we found no
1099 checkpoint > newvalue, as
1100 then rightcheckpt == ncheckpts */
1101 /* the following loop is always ran at least once, as
1102 nodes[checkpts[rightcheckpt-1]].value < newvalue
1103 after 'find checkpoint' loop */
1104 while((nextnode != nil) && (newvalue > nodes[nextnode].value)) {
1105 prevnode = nextnode;
1106 nextnode = nodes[nextnode].greater;
1107 }
1108 }
1109 /* ok, we have:
1110 - case 1: insert at beginning: prevnode == nil, nextnode == smallest node
1111 - case 2: insert at end: nextnode == nil (terminated loop),
1112 prevnode == last node
1113 - case 3: ordinary insert: insert between prevnode and nextnode
1114 */
1115
1116 /* insertion deletion and shifting are unnecessary if we are replacing
1117 at the same pos */
1118 if ((oldestnode != prevnode) && (oldestnode != nextnode)) {
1119
1120 /* delete oldest node from list */
1121 if (nodes[oldestnode].lesser == nil) {
1122 /* case 1: at beginning */
1123 nodes[nodes[oldestnode].greater].lesser = nil;
1124 /* this shouldn't be necessary, but doesn't harm */
1125 checkpts[0] = nodes[oldestnode].greater;
1126 } else if (nodes[oldestnode].greater == nil)
1127 /* case 2: at end */
1128 nodes[nodes[oldestnode].lesser].greater = nil;
1129 else {
1130 /* case 3: anywhere else */
1131 nodes[nodes[oldestnode].lesser].greater = nodes[oldestnode].greater;
1132 nodes[nodes[oldestnode].greater].lesser = nodes[oldestnode].lesser;
1133 }
1134 /* remember the old links for special case in shifting below */
1135 oldgreater = nodes[oldestnode].greater;
1136 oldlesser = nodes[oldestnode].lesser;
1137
1138
1139 /* insert new node - actually we reuse the oldest one */
1140 /* the value is set outside the outer "if" */
1141 nodes[oldestnode].lesser = prevnode;
1142 nodes[oldestnode].greater = nextnode;
1143 if (prevnode != nil)
1144 nodes[prevnode].greater = oldestnode;
1145 if (nextnode != nil)
1146 nodes[nextnode].lesser = oldestnode;
1147
1148
1149 /* shift checkpoints */
1150
1151 /* if there is a sequence of identical values, new values are inserted
1152 always at the left end. Thus, the oldest value has to be the rightmost
1153 of such a sequence. This requires proper init.
1154
1155 This makes shifting of the checkpoints rather easy:
1156 if (oldvalue < newvalue), all checkpoints with
1157 oldvalue <(=) chkptvalue < newvalue are shifted,
1158 if (newvalue <= oldvalue), all checkpoints with
1159 newvalue <= chkptvalue <= oldvalue are shifted.
1160 <(=) means that only a checkpoint at the deleted node must be
1161 shifted, no other accidently pointing to the same value.
1162
1163 Care is needed if a checkpoint to shift is the node we just deleted
1164
1165 We start at the checkpoint we know to be closest to the new node
1166 satifying the above condition:
1167 rightcheckpt-1 if (oldvalue < newvalue)
1168 rightcheckpt othewise
1169 and proceed in the direction towards the deleted node
1170 */
1171
1172 if (oldvalue < newvalue) {
1173 /* we shift towards larger values */
1174 for(j=rightcheckpt-1; (j>0)&&(nodes[checkpts[j]].value >= oldvalue);j--)
1175 if (nodes[checkpts[j]].value > oldvalue)
1176 checkpts[j] = nodes[checkpts[j]].greater;
1177 else if (checkpts[j] == oldestnode)
1178 checkpts[j] = oldgreater;
1179 } else /* newvalue <= oldvalue */
1180 /* we shift towards smaller values */
1181 for(i=rightcheckpt;
1182 (i<ncheckpts) && (nodes[checkpts[i]].value <= oldvalue); i++)
1183 if (checkpts[i] == oldestnode)
1184 checkpts[i] = oldlesser;
1185 else
1186 checkpts[i] = nodes[checkpts[i]].lesser;
1187
1188 } /* if ((oldestnode != prevnode) && (oldestnode != nextnode)) */
1189
1190 /* in any case set new value */
1191 nodes[oldestnode].value = newvalue;
1192
1193
1194 /* find median */
1195 if (newvalue == oldvalue)
1196 medians->data[nmedian] = medians->data[nmedian-1];
1197 else {
1198 nextnode = checkpts[mdnnearest];
1199 if(isodd)
1200 medians->data[nmedian] = nodes[nextnode].value;
1201 else
1202 medians->data[nmedian] = (nodes[nextnode].value
1203 + nodes[nodes[nextnode].greater].value) / 2.0;
1204 }
1205
1206 /* next oldest node */
1207 oldestnode = (oldestnode + 1) % bsize; /* wrap around */
1208
1209 } /* for (nmedian...) */
1210
1211 /* cleanup */
1212 LALFree(checkpts);
1213 LALFree(nodes);
1214
1216 RETURN( status );
1217}
1218
1219
1221 REAL4Sequence *medians,
1222 const REAL4Sequence *input,
1223 LALRunningMedianPar param)
1224
1225{
1226 /* a single "node"
1227 lesser points to the next node with less or equal value
1228 greater points to the next node with greater or equal value
1229 an index == blocksize is an end marker
1230 */
1231 struct node{
1232 REAL4 value;
1233 UINT4 lesser;
1234 UINT4 greater;
1235 };
1236
1237 /* a node of the quicksort array */
1238 struct qsnode{
1239 REAL4 value;
1240 UINT4 index;
1241 };
1242
1243 const UINT4 bsize = param.blocksize; /* just an abbrevation */
1244 const UINT4 nil = bsize; /* invalid index used as end marker */
1245 const BOOLEAN isodd = bsize&1; /* bsize is odd = median is a single element */
1246
1247 struct node* nodes; /* array of nodes, will be of size blocksize */
1248 struct qsnode* qsnodes; /* array of indices for initial qsort */
1249 UINT4* checkpts; /* array of checkpoints */
1250 UINT4 ncheckpts,stepchkpts; /* checkpoints: number and distance between */
1251 UINT4 oldestnode; /* index of "oldest" node */
1252 UINT4 i; /* loop counter (up to input length) */
1253 INT4 j; /* loop counter (might get negative) */
1254 UINT4 nmedian; /* current median, outer loop counter */
1255 UINT4 midpoint; /* index of middle node in sorting order */
1256 UINT4 mdnnearest; /* checkpoint "nearest" to the median */
1257 UINT4 nextnode; /* node after an insertion point,
1258 also used to find a median */
1259 UINT4 prevnode; /* node before an insertion point */
1260 UINT4 rightcheckpt; /* checkpoint 'right' of an insertion point */
1261 REAL4 oldvalue,newvalue; /* old + new value of the node being replaced */
1262 UINT4 oldlesser,oldgreater; /* remember the pointers of the replaced node */
1263
1265
1266 /* check input parameters */
1267 /* input must not be NULL */
1268 ASSERT(input,status,LALRUNNINGMEDIANH_ENULL,LALRUNNINGMEDIANH_MSGENULL);
1269 /* param.blocksize must be >2 */
1270 ASSERT(param.blocksize>2,
1271 status,LALRUNNINGMEDIANH_EZERO,LALRUNNINGMEDIANH_MSGEZERO);
1272 /* blocksize must not be larger than input size */
1273 ASSERT(param.blocksize <= input->length,
1274 status,LALRUNNINGMEDIANH_ELARGE,LALRUNNINGMEDIANH_MSGELARGE);
1275 /* medians must point to a valid sequence of correct size */
1276 ASSERT(medians,status,LALRUNNINGMEDIANH_EIMED,LALRUNNINGMEDIANH_MSGEIMED);
1277 ASSERT(medians->length == (input->length - param.blocksize + 1),
1278 status,LALRUNNINGMEDIANH_EIMED,LALRUNNINGMEDIANH_MSGEIMED);
1279
1281
1282 /* create nodes array */
1283 nodes = (struct node*)LALCalloc(bsize, sizeof(struct node));
1284
1285 /* determine checkpoint positions */
1286 stepchkpts = sqrt(bsize);
1287 /* the old form
1288 ncheckpts = bsize/stepchkpts;
1289 caused too less checkpoints at the end, leading to break the
1290 cost calculation */
1291 ncheckpts = ceil((REAL4)bsize/(REAL4)stepchkpts);
1292
1293 /* set checkpoint nearest to the median and offset of the median to it */
1294 midpoint = (bsize+(bsize&1)) / 2 - 1;
1295 /* this becomes the median checkpoint */
1296 mdnnearest = ceil((REAL4)midpoint / (REAL4)stepchkpts);
1297
1298 /* add a checkpoint for the median if necessary */
1299 if (ceil((REAL4)midpoint / (REAL4)stepchkpts) != (REAL4)midpoint / (REAL4)stepchkpts)
1300 ncheckpts++;
1301
1302 /* create checkpoints array */
1303 checkpts = (UINT4*)LALCalloc(ncheckpts,sizeof(UINT4));
1304
1305 /* create array for qsort */
1306 qsnodes = (struct qsnode*)LALCalloc(bsize, sizeof(struct qsnode));
1307
1308 /* init qsort array
1309 the nodes get their values from the input,
1310 the indices are only identities qi[0]=0,qi[1]=1,... */
1311 for(i=0;i<bsize;i++) {
1312 qsnodes[i].value = input->data[i];
1313 qsnodes[i].index = i;
1314 }
1315
1316 /* sort qsnodes by value and index(!) */
1317 qsort(qsnodes, bsize, sizeof(struct qsnode),rngmed_qsortindex4);
1318
1319 /* init nodes array */
1320 for(i=0;i<bsize;i++)
1321 nodes[i].value = input->data[i];
1322 for(i=1;i<bsize-1;i++) {
1323 nodes[qsnodes[i-1].index].greater = qsnodes[i].index;
1324 nodes[qsnodes[i+1].index].lesser = qsnodes[i].index;
1325 }
1326 nodes[qsnodes[0].index].lesser = nil; /* end marker */
1327 nodes[qsnodes[1].index].lesser = qsnodes[0].index;
1328 nodes[qsnodes[bsize-2].index].greater = qsnodes[bsize-1].index;
1329 nodes[qsnodes[bsize-1].index].greater = nil; /* end marker */
1330
1331 /* setup checkpoints */
1332 /* j is the current checkpoint
1333 i is the stepping
1334 they are out of sync after a median checkpoint has been added */
1335 for(i=0,j=0; (UINT4)j<ncheckpts; i++,j++) {
1336 if ((UINT4)j == mdnnearest) {
1337 checkpts[j] = qsnodes[midpoint].index;
1338 if (i*stepchkpts != midpoint)
1339 j++;
1340 }
1341 checkpts[j] = qsnodes[i*stepchkpts].index;
1342 }
1343
1344 /* don't need the qsnodes anymore */
1345 LALFree(qsnodes);
1346
1347 /* find first median */
1348 nextnode = checkpts[mdnnearest];
1349 if(isodd)
1350 medians->data[0] = nodes[nextnode].value;
1351 else
1352 medians->data[0] = (nodes[nextnode].value
1353 + nodes[nodes[nextnode].greater].value) / 2.0;
1354
1355 /* the "oldest" node (first in sequence) is the one with index 0 */
1356 oldestnode = 0;
1357
1358 /* outer loop: find a median with each iteration */
1359 for(nmedian=1; nmedian < medians->length; nmedian++) {
1360
1361 /* remember value of sample to be deleted */
1362 oldvalue = nodes[oldestnode].value;
1363
1364 /* get next value to be inserted from input */
1365 newvalue = input->data[nmedian+bsize-1];
1366
1367 /** find point of insertion: **/
1368
1369 /* find checkpoint greater or equal newvalue */
1370 /* possible optimisation: use bisectional search instaed of linear */
1371 for(rightcheckpt=0; rightcheckpt<ncheckpts; rightcheckpt++)
1372 if(newvalue <= nodes[checkpts[rightcheckpt]].value)
1373 break;
1374
1375 /* assume we are inserting at the beginning: */
1376 prevnode = nil;
1377 if (rightcheckpt == 0)
1378 /* yes, we are */
1379 nextnode = checkpts[0];
1380 else {
1381 /* we're beyond the first checkpoint, find the node we're inserting at: */
1382 nextnode = checkpts[rightcheckpt-1]; /* this also works if we found no
1383 checkpoint > newvalue, as
1384 then rightcheckpt == ncheckpts */
1385 /* the following loop is always ran at least once, as
1386 nodes[checkpts[rightcheckpt-1]].value < newvalue
1387 after 'find checkpoint' loop */
1388 while((nextnode != nil) && (newvalue > nodes[nextnode].value)) {
1389 prevnode = nextnode;
1390 nextnode = nodes[nextnode].greater;
1391 }
1392 }
1393 /* ok, we have:
1394 - case 1: insert at beginning: prevnode == nil, nextnode == smallest node
1395 - case 2: insert at end: nextnode == nil (terminated loop),
1396 prevnode == last node
1397 - case 3: ordinary insert: insert between prevnode and nextnode
1398 */
1399
1400 /* insertion deletion and shifting are unnecessary if we are replacing
1401 at the same pos */
1402 if ((oldestnode != prevnode) && (oldestnode != nextnode)) {
1403
1404 /* delete oldest node from list */
1405 if (nodes[oldestnode].lesser == nil) {
1406 /* case 1: at beginning */
1407 nodes[nodes[oldestnode].greater].lesser = nil;
1408 /* this shouldn't be necessary, but doesn't harm */
1409 checkpts[0] = nodes[oldestnode].greater;
1410 } else if (nodes[oldestnode].greater == nil)
1411 /* case 2: at end */
1412 nodes[nodes[oldestnode].lesser].greater = nil;
1413 else {
1414 /* case 3: anywhere else */
1415 nodes[nodes[oldestnode].lesser].greater = nodes[oldestnode].greater;
1416 nodes[nodes[oldestnode].greater].lesser = nodes[oldestnode].lesser;
1417 }
1418 /* remember the old links for special case in shifting below */
1419 oldgreater = nodes[oldestnode].greater;
1420 oldlesser = nodes[oldestnode].lesser;
1421
1422
1423 /* insert new node - actually we reuse the oldest one */
1424 /* the value is set outside the outer "if" */
1425 nodes[oldestnode].lesser = prevnode;
1426 nodes[oldestnode].greater = nextnode;
1427 if (prevnode != nil)
1428 nodes[prevnode].greater = oldestnode;
1429 if (nextnode != nil)
1430 nodes[nextnode].lesser = oldestnode;
1431
1432
1433 /* shift checkpoints */
1434
1435 /* if there is a sequence of identical values, new values are inserted
1436 always at the left end. Thus, the oldest value has to be the rightmost
1437 of such a sequence. This requires proper init.
1438
1439 This makes shifting of the checkpoints rather easy:
1440 if (oldvalue < newvalue), all checkpoints with
1441 oldvalue <(=) chkptvalue < newvalue are shifted,
1442 if (newvalue <= oldvalue), all checkpoints with
1443 newvalue <= chkptvalue <= oldvalue are shifted.
1444 <(=) means that only a checkpoint at the deleted node must be
1445 shifted, no other accidently pointing to the same value.
1446
1447 Care is needed if a checkpoint to shift is the node we just deleted
1448
1449 We start at the checkpoint we know to be closest to the new node
1450 satifying the above condition:
1451 rightcheckpt-1 if (oldvalue < newvalue)
1452 rightcheckpt othewise
1453 and proceed in the direction towards the deleted node
1454 */
1455
1456 if (oldvalue < newvalue) {
1457 /* we shift towards larger values */
1458 for(j=rightcheckpt-1; (j>0)&&(nodes[checkpts[j]].value >= oldvalue);j--)
1459 if (nodes[checkpts[j]].value > oldvalue)
1460 checkpts[j] = nodes[checkpts[j]].greater;
1461 else if (checkpts[j] == oldestnode)
1462 checkpts[j] = oldgreater;
1463 } else /* newvalue <= oldvalue */
1464 /* we shift towards smaller values */
1465 for(i=rightcheckpt;
1466 (i<ncheckpts) && (nodes[checkpts[i]].value <= oldvalue); i++)
1467 if (checkpts[i] == oldestnode)
1468 checkpts[i] = oldlesser;
1469 else
1470 checkpts[i] = nodes[checkpts[i]].lesser;
1471
1472 } /* if ((oldestnode != prevnode) && (oldestnode != nextnode)) */
1473
1474 /* in any case set new value */
1475 nodes[oldestnode].value = newvalue;
1476
1477
1478 /* find median */
1479 if (newvalue == oldvalue)
1480 medians->data[nmedian] = medians->data[nmedian-1];
1481 else {
1482 nextnode = checkpts[mdnnearest];
1483 if(isodd)
1484 medians->data[nmedian] = nodes[nextnode].value;
1485 else
1486 medians->data[nmedian] = (nodes[nextnode].value
1487 + nodes[nodes[nextnode].greater].value) / 2.0;
1488 }
1489
1490 /* next oldest node */
1491 oldestnode = (oldestnode + 1) % bsize; /* wrap around */
1492
1493 } /* for (nmedian...) */
1494
1495 /* cleanup */
1496 LALFree(checkpts);
1497 LALFree(nodes);
1498
1500 RETURN( status );
1501}
#define LALCalloc(m, n)
Definition: LALMalloc.h:94
#define LALFree(p)
Definition: LALMalloc.h:96
static int rngmed_qsortindex8(const void *elem1, const void *elem2)
static int rngmed_sortindex8(const void *elem1, const void *elem2)
static int rngmed_sortindex4(const void *elem1, const void *elem2)
static int rngmed_qsortindex4(const void *elem1, const void *elem2)
#define ABORT(statusptr, code, mesg)
#define ATTATCHSTATUSPTR(statusptr)
#define ASSERT(assertion, statusptr, code, mesg)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
unsigned char BOOLEAN
Boolean logical type, see Headers LAL(Atomic)Datatypes.h for more details.
double REAL8
Double precision real floating-point number (8 bytes).
int64_t INT8
Eight-byte signed integer; on some platforms this is equivalent to long int instead.
uint32_t UINT4
Four-byte unsigned integer.
int32_t INT4
Four-byte signed integer.
float REAL4
Single precision real floating-point number (4 bytes).
void LALSRunningMedian(LALStatus *status, REAL4Sequence *medians, const REAL4Sequence *input, LALRunningMedianPar param)
See LALRunningMedian_h for documentation.
#define LALRUNNINGMEDIANH_EMALOC3
Could not allocate checks4shift.
void LALDRunningMedian(LALStatus *status, REAL8Sequence *medians, const REAL8Sequence *input, LALRunningMedianPar param)
See LALRunningMedian_h for documentation.
#define LALRUNNINGMEDIANH_ENULL
Invalid input: NULL pointer.
void LALDRunningMedian2(LALStatus *status, REAL8Sequence *medians, const REAL8Sequence *input, LALRunningMedianPar param)
See LALRunningMedian_h for documentation.
#define LALRUNNINGMEDIANH_EMALOC6
Could not allocate node.
#define LALRUNNINGMEDIANH_EMALOC4
Could not allocate nodeaddresses.
#define LALRUNNINGMEDIANH_ELARGE
Invalid input: block length larger than imput length.
#define LALRUNNINGMEDIANH_EMALOC2
Could not allocate checks.
#define LALRUNNINGMEDIANH_EMALOC1
Could not allocate indexblock.
#define LALRUNNINGMEDIANH_EZERO
Invalid input: block length must be >2.
void LALSRunningMedian2(LALStatus *status, REAL4Sequence *medians, const REAL4Sequence *input, LALRunningMedianPar param)
See LALRunningMedian_h for documentation.
#define LALRUNNINGMEDIANH_EMALOC5
Could not aloocate first node.
#define LALRUNNINGMEDIANH_EIMED
Invalid input: wrong size of median array.
This is the parameter structure for the LALRunningMedian functions.
UINT4 blocksize
the number of elements a single median is calculated from
LAL status structure, see The LALStatus structure for more details.
Definition: LALDatatypes.h:947
Vector of type REAL4, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:145
REAL4 * data
Pointer to the data array.
Definition: LALDatatypes.h:150
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:149
Vector of type REAL8, see DATATYPE-Vector types for more details.
Definition: LALDatatypes.h:154
REAL8 * data
Pointer to the data array.
Definition: LALDatatypes.h:159
UINT4 length
Number of elements in array.
Definition: LALDatatypes.h:158