LAL  7.5.0.1-ec27e42
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 
42 static 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 
59 static 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 */
78 static 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 */
98 static 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,
121  LALRunningMedianPar param)
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,
529  LALRunningMedianPar param)
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,
939  LALRunningMedianPar param)
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 
1264  INITSTATUS(status);
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