Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-b246709
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
CacheResults.c
Go to the documentation of this file.
1//
2// Copyright (C) 2016, 2017 Karl Wette
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///
21/// \file
22/// \ingroup lalpulsar_bin_Weave
23///
24
25#include "CacheResults.h"
26
27#include <lal/LALHeap.h>
28#include <lal/LALHashTbl.h>
29#include <lal/LALBitset.h>
30
31// Compare two quantities, and return a sort order value if they are unequal
32#define COMPARE_BY( x, y ) do { if ( (x) < (y) ) return -1; if ( (x) > (y) ) return +1; } while(0)
33
34///
35/// Item stored in the cache
36///
37typedef struct {
38 /// Generation, used both to find items in cache and to decide how long to keep items
40 /// Relevance, used to decide how long to keep items
42 /// Coherent locator index, used to find items in cache
44 /// Results of a coherent computation on a single segment
45 WeaveCohResults *coh_res;
47
48///
49/// Container for a series of cache queries
50///
52 /// Number of parameter-space dimensions
53 size_t ndim;
54 /// Lowest tiled parameter-space dimension
55 size_t dim0;
56 // Frequency spacing used by lattices
57 double dfreq;
58 /// Number of queries for which space is allocated
60 /// Number of partitions to divide semicoherent frequency block into
62 /// Index to current partition of semicoherent frequency block
64 /// Offset to apply to coherent left-most index to enclose a frequency partition
66 /// Offset to apply to coherent right-most index to enclose a frequency partition
68 /// Sequential indexes for each queried coherent frequency block
70 /// Physical points of each queried coherent frequency block
72 /// Indexes of left-most point in queried coherent frequency block
74 /// Indexes of right-most point in queried coherent frequency block
76 /// Relevance of each queried coherent frequency block
78 /// Number of computed coherent results (per query)
80 /// Number of coherent templates (per query)
82 /// Reduced supersky transform data for semicoherent lattice
83 const SuperskyTransformData *semi_rssky_transf;
84 /// Sequential index for the current semicoherent frequency block
86 // Current semicoherent frequency block in dimension 'dim0'
88 /// Physical coordinates of the current semicoherent frequency block
90 /// Index of left-most point in current semicoherent frequency block
92 /// Index of right-most point in current semicoherent frequency block
94 /// Relevance of the current semicoherent frequency block
96 /// Offset used in computation of semicoherent point relevance
98 /// Number of semicoherent templates (over all queries)
100};
101
102///
103/// Cache used to store coherent results
104///
106 /// Number of parameter-space dimensions
107 size_t ndim;
108 /// Lowest tiled parameter-space dimension
109 size_t dim0;
110 /// Reduced supersky transform data for coherent lattice
111 const SuperskyTransformData *coh_rssky_transf;
112 /// Reduced supersky transform data for semicoherent lattice
113 const SuperskyTransformData *semi_rssky_transf;
114 /// Input data required for computing coherent results
115 WeaveCohInput *coh_input;
116 /// Coherent parameter-space tiling locator
117 LatticeTilingLocator *coh_locator;
118 /// Maximum value of index from coherent locator
120 /// Current generation of cache items
122 /// Heap which ranks cache items by relevance
124 /// Maximum size obtained by relevance heap
126 /// Hash table which looks up cache items by index
127 LALHashTbl *coh_index_hash;
128 /// Bitset which records whether an item has ever been computed
130 /// Offset used in computation of coherent point relevance
132 /// Whether any garbage collection of results should be used
134 /// Whether garbage collection should remove as many results as possible
136 /// Save an no-longer-used cache item for re-use
138};
139
140///
141/// \name Internal functions
142///
143/// @{
144
145static int cache_left_right_offsets( const UINT4 semi_nfreqs, const UINT4 nfreq_partitions, const UINT4 freq_partition_index, INT4 *left_offset, INT4 *right_offset );
146static int cache_max_semi_bbox_sample_dim0( const WeaveCache *cache, const LatticeTiling *coh_tiling, const size_t i, gsl_vector *coh_bbox_sample, gsl_vector *semi_bbox_sample, double *max_semi_bbox_sample_dim0 );
147static UINT8 cache_item_hash( const void *x );
148static int cache_item_compare_by_coh_index( const void *x, const void *y );
149static int cache_item_compare_by_relevance( const void *x, const void *y );
150static void cache_item_destroy( void *x );
151
152/// @}
153
154///
155/// Destroy a cache item
156///
158 void *x
159)
160{
161 if ( x != NULL ) {
162 cache_item *ix = ( cache_item * ) x;
164 XLALFree( ix );
165 }
166}
167
168///
169/// Compare cache items by generation, then relevance
170///
172 const void *x,
173 const void *y
174)
175{
176 const cache_item *ix = ( const cache_item * ) x;
177 const cache_item *iy = ( const cache_item * ) y;
178 COMPARE_BY( ix->generation, iy->generation ); // Compare in ascending order
179 COMPARE_BY( ix->relevance, iy->relevance ); // Compare in ascending order
180 return 0;
181}
182
183///
184/// Compare cache items by generation, then locator index
185///
187 const void *x,
188 const void *y
189)
190{
191 const cache_item *ix = ( const cache_item * ) x;
192 const cache_item *iy = ( const cache_item * ) y;
193 COMPARE_BY( ix->generation, iy->generation ); // Compare in ascending order
194 COMPARE_BY( ix->coh_index, iy->coh_index ); // Compare in ascending order
195 return 0;
196}
197
198///
199/// Hash cache items by generation and locator index
200///
202 const void *x
203)
204{
205 const cache_item *ix = ( const cache_item * ) x;
206 UINT4 hval = 0;
207 XLALPearsonHash( &hval, sizeof( hval ), &ix->generation, sizeof( ix->generation ) );
208 XLALPearsonHash( &hval, sizeof( hval ), &ix->coh_index, sizeof( ix->coh_index ) );
209 return hval;
210}
211
212///
213/// Sample points on surface of coherent bounding box, convert to semicoherent supersky
214/// coordinates, and record maximum value of semicoherent coordinate in dimension 'dim0'
215///
217 const WeaveCache *cache,
218 const LatticeTiling *coh_tiling,
219 const size_t i,
220 gsl_vector *coh_bbox_sample,
221 gsl_vector *semi_bbox_sample,
222 double *max_semi_bbox_sample_dim0
223)
224{
225
226 if ( i < cache->ndim ) {
227
228 // Get coherent lattice tiling bounding box in dimension 'i'
229 const double coh_bbox_i = XLALLatticeTilingBoundingBox( coh_tiling, i );
231
232 // Get current value of 'coh_bbox_sample' in dimension 'i'
233 const double coh_bbox_sample_i = gsl_vector_get( coh_bbox_sample, i );
234
235 // Move 'coh_bbox_sample' in dimension 'i' to vertices, edge centres and face centres of bounding box, and proceed to higher dimensions
236 for ( int step = -1; step <= 1; ++ step ) {
237 gsl_vector_set( coh_bbox_sample, i, coh_bbox_sample_i - step * 0.5 * coh_bbox_i );
238 XLAL_CHECK( cache_max_semi_bbox_sample_dim0( cache, coh_tiling, i + 1, coh_bbox_sample, semi_bbox_sample, max_semi_bbox_sample_dim0 ) == XLAL_SUCCESS, XLAL_EFUNC );
239 }
240
241 // Restore current value of 'coh_bbox_sample' in dimension 'i'
242 gsl_vector_set( coh_bbox_sample, i, coh_bbox_sample_i );
243
244 } else {
245
246 // Convert 'coh_bbox_sample' to semicoherent reduced supersky coordinates
247 XLAL_CHECK( XLALConvertSuperskyToSuperskyPoint( semi_bbox_sample, cache->semi_rssky_transf, coh_bbox_sample, coh_bbox_sample, cache->coh_rssky_transf ) == XLAL_SUCCESS, XLAL_EINVAL );
248
249 // Record maximum value of semicoherent coordinate in dimension 'dim0'
250 *max_semi_bbox_sample_dim0 = GSL_MAX( *max_semi_bbox_sample_dim0, gsl_vector_get( semi_bbox_sample, cache->dim0 ) );
251
252 }
253
254 return XLAL_SUCCESS;
255
256}
257
258///
259/// Compute left/right-most index offsets to select a given partition
260///
262 const UINT4 semi_nfreqs,
263 const UINT4 nfreq_partitions,
264 const UINT4 freq_partition_index,
265 INT4 *left_offset,
266 INT4 *right_offset
267)
268{
269
270 // Minimum number of points in the current frequency partition
271 const UINT4 min_part_nfreqs = semi_nfreqs / nfreq_partitions;
272
273 // Excess number of points which must be added to get 'semi_nfreqs' in total
274 INT4 excess_nfreqs = semi_nfreqs - nfreq_partitions * min_part_nfreqs;
275
276 // Initialise number of points in this frequency partition
277 // - If there are excess points, add an extra point
278 INT4 part_nfreqs = min_part_nfreqs;
279 if ( excess_nfreqs > 0 ) {
280 ++part_nfreqs;
281 }
282
283 // Compute offsets to left/right-most indexes to the select each given partition
284 // - Add 'part_nfreqs' to '*left_offset' for each increase in partition index
285 // - Decrease number of excess points; if zero, subtract extra point from 'part_nfreqs'
286 *left_offset = 0;
287 for ( size_t i = 0; i < freq_partition_index; ++i ) {
288 *left_offset += part_nfreqs;
289 --excess_nfreqs;
290 if ( excess_nfreqs == 0 ) {
291 --part_nfreqs;
292 }
293 }
294 *right_offset = *left_offset + part_nfreqs - semi_nfreqs;
295 XLAL_CHECK( *left_offset >= 0, XLAL_EDOM );
296 XLAL_CHECK( *right_offset <= 0, XLAL_EDOM );
297
298 return XLAL_SUCCESS;
299
300}
301
302///
303/// Create storage for a series of cache queries
304///
306 const LatticeTiling *semi_tiling,
307 const SuperskyTransformData *semi_rssky_transf,
308 const double dfreq,
309 const UINT4 nqueries,
310 const UINT4 nfreq_partitions
311)
312{
313
314 // Check input
315 XLAL_CHECK_NULL( semi_tiling != NULL, XLAL_EFAULT );
317 XLAL_CHECK_NULL( nqueries > 0, XLAL_EINVAL );
318 XLAL_CHECK_NULL( nfreq_partitions > 0, XLAL_EINVAL );
319
320 // Allocate memory
321 WeaveCacheQueries *queries = XLALCalloc( 1, sizeof( *queries ) );
322 XLAL_CHECK_NULL( queries != NULL, XLAL_ENOMEM );
323 queries->coh_part_left_offset = XLALCalloc( nfreq_partitions, sizeof( *queries->coh_part_left_offset ) );
324 XLAL_CHECK_NULL( queries->coh_part_left_offset != NULL, XLAL_ENOMEM );
325 queries->coh_part_right_offset = XLALCalloc( nfreq_partitions, sizeof( *queries->coh_part_right_offset ) );
326 XLAL_CHECK_NULL( queries->coh_part_right_offset != NULL, XLAL_ENOMEM );
327 queries->coh_index = XLALCalloc( nqueries, sizeof( *queries->coh_index ) );
328 XLAL_CHECK_NULL( queries->coh_index != NULL, XLAL_ENOMEM );
329 queries->coh_phys = XLALCalloc( nqueries, sizeof( *queries->coh_phys ) );
330 XLAL_CHECK_NULL( queries->coh_phys != NULL, XLAL_ENOMEM );
331 queries->coh_left = XLALCalloc( nqueries, sizeof( *queries->coh_left ) );
332 XLAL_CHECK_NULL( queries->coh_left != NULL, XLAL_ENOMEM );
333 queries->coh_right = XLALCalloc( nqueries, sizeof( *queries->coh_right ) );
334 XLAL_CHECK_NULL( queries->coh_right != NULL, XLAL_ENOMEM );
335 queries->coh_relevance = XLALCalloc( nqueries, sizeof( *queries->coh_relevance ) );
336 XLAL_CHECK_NULL( queries->coh_relevance != NULL, XLAL_ENOMEM );
337 queries->coh_nres = XLALCalloc( nqueries, sizeof( *queries->coh_nres ) );
338 XLAL_CHECK_NULL( queries->coh_nres != NULL, XLAL_ENOMEM );
339 queries->coh_ntmpl = XLALCalloc( nqueries, sizeof( *queries->coh_ntmpl ) );
340 XLAL_CHECK_NULL( queries->coh_ntmpl != NULL, XLAL_ENOMEM );
341
342 // Set fields
343 queries->semi_rssky_transf = semi_rssky_transf;
344 queries->dfreq = dfreq;
345 queries->nqueries = nqueries;
346 queries->nfreq_partitions = nfreq_partitions;
347
348 // Get number of parameter-space dimensions
349 queries->ndim = XLALTotalLatticeTilingDimensions( semi_tiling );
351
352 // Get lowest tiled parameter-space dimension
353 if ( XLALTiledLatticeTilingDimensions( semi_tiling ) > 0 ) {
354 queries->dim0 = XLALLatticeTilingTiledDimension( semi_tiling, 0 );
355 } else {
356 queries->dim0 = 0;
357 }
359
360 // Compute offset used in computation of semicoherent point relevance:
361 // - Negative half of semicoherent lattice tiling bounding box in dimension 'dim0'
362 queries->semi_relevance_offset = -0.5 * XLALLatticeTilingBoundingBox( semi_tiling, queries->dim0 );
364
365 // Minimum number of points in a semicoherent frequency block
366 const LatticeTilingStats *stats = XLALLatticeTilingStatistics( semi_tiling, queries->ndim - 1 );
367 XLAL_CHECK_NULL( stats != NULL, XLAL_EFUNC );
368 XLAL_CHECK_NULL( stats->min_points > 0, XLAL_EFAILED );
369
370 // Compute offsets to coherent left/right-most indexes to enclose each frequency partition
371 // - Use 'semi_min_freqs' to make offsets less than or equal to any semicoherent offsets
372 for ( size_t i = 0; i < queries->nfreq_partitions; ++i ) {
373 XLAL_CHECK_NULL( cache_left_right_offsets( stats->min_points, queries->nfreq_partitions, i, &queries->coh_part_left_offset[i], &queries->coh_part_right_offset[i] ) == XLAL_SUCCESS, XLAL_EFUNC );
374 }
375
376 return queries;
377
378}
379
380///
381/// Destroy storage for a series of cache queries
382///
384 WeaveCacheQueries *queries
385)
386{
387 if ( queries != NULL ) {
388 XLALFree( queries->coh_part_left_offset );
389 XLALFree( queries->coh_part_right_offset );
390 XLALFree( queries->coh_index );
391 XLALFree( queries->coh_phys );
392 XLALFree( queries->coh_left );
393 XLALFree( queries->coh_right );
394 XLALFree( queries->coh_relevance );
395 XLALFree( queries->coh_nres );
396 XLALFree( queries->coh_ntmpl );
397 XLALFree( queries );
398 }
399}
400
401///
402/// Initialise a series of cache queries
403///
405 WeaveCacheQueries *queries,
406 const UINT8 semi_index,
407 const gsl_vector *semi_rssky,
408 const INT4 semi_left,
409 const INT4 semi_right,
410 const UINT4 freq_partition_index
411)
412{
413
414 // Check input
415 XLAL_CHECK( queries != NULL, XLAL_EFAULT );
416 XLAL_CHECK( semi_rssky != NULL, XLAL_EFAULT );
417 XLAL_CHECK( freq_partition_index < queries->nfreq_partitions, XLAL_EINVAL );
418
419 // Reset coherent sequential indexes to zero, indicating no query
420 memset( queries->coh_index, 0, queries->nqueries * sizeof( queries->coh_index[0] ) );
421
422 // Save current semicoherent sequential index
423 queries->semi_index = semi_index;
424
425 // Save current semicoherent frequency block in dimension 'dim0'
426 queries->semi_rssky_dim0 = gsl_vector_get( semi_rssky, queries->dim0 );
427
428 // Convert semicoherent point to physical coordinates
429 XLAL_CHECK( XLALConvertSuperskyToPhysicalPoint( &queries->semi_phys, semi_rssky, NULL, queries->semi_rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC );
430
431 // Save indexes of left/right-most point in current semicoherent frequency block
432 queries->semi_left = semi_left;
433 queries->semi_right = semi_right;
434
435 // Save index to current partition of semicoherent frequency block
436 queries->freq_partition_index = freq_partition_index;
437
438 // Compute the relevance of the current semicoherent frequency block
439 // - Relevance is semicoherent reduced supersky point in dimension 'dim0', plus offset
440 queries->semi_relevance = gsl_vector_get( semi_rssky, queries->dim0 ) + queries->semi_relevance_offset;
441
442 return XLAL_SUCCESS;
443
444}
445
446///
447/// Query a cache for the results nearest to a given coherent point
448///
450 const WeaveCache *cache,
451 WeaveCacheQueries *queries,
452 const UINT4 query_index
453)
454{
455
456 // Check input
457 XLAL_CHECK( cache != NULL, XLAL_EFAULT );
458 XLAL_CHECK( queries != NULL, XLAL_EFAULT );
459 XLAL_CHECK( cache->ndim == queries->ndim, XLAL_ESIZE );
460 XLAL_CHECK( cache->dim0 == queries->dim0, XLAL_ESIZE );
461 XLAL_CHECK( query_index < queries->nqueries, XLAL_EINVAL );
462
463 // Convert semicoherent physical point to coherent reduced supersky coordinates
464 double coh_point_array[cache->ndim];
465 gsl_vector_view coh_point_view = gsl_vector_view_array( coh_point_array, cache->ndim );
466 XLAL_CHECK( XLALConvertPhysicalToSuperskyPoint( &coh_point_view.vector, &queries->semi_phys, cache->coh_rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC );
467
468 // Initialise nearest point to semicoherent point in coherent reduced supersky coordinates
469 double coh_near_point_array[cache->ndim];
470 gsl_vector_view coh_near_point_view = gsl_vector_view_array( coh_near_point_array, cache->ndim );
471 gsl_vector_memcpy( &coh_near_point_view.vector, &coh_point_view.vector );
472
473 // Initialise values for a non-interpolating search
474 queries->coh_index[query_index] = queries->semi_index;
475 queries->coh_left[query_index] = queries->semi_left;
476 queries->coh_right[query_index] = queries->semi_right;
477
478 // If performing an interpolating search, find the nearest coherent frequency pass in this segment
479 // - 'coh_near_point' is set to the nearest point to the mid-point of the semicoherent frequency block
480 // - 'coh_index' is set to the index of this coherent frequency block, used for cache lookup
481 // - 'coh_left' and 'coh_right' are set of number of points to the left/right of 'coh_near_point';
482 // check that these are sufficient to contain the number of points to the left/right of 'semi_rssky'
483 if ( cache->coh_locator != NULL ) {
484 XLAL_CHECK( XLALNearestLatticeTilingBlock( cache->coh_locator, &coh_point_view.vector, cache->ndim - 1, &coh_near_point_view.vector, &queries->coh_index[query_index], &queries->coh_left[query_index], &queries->coh_right[query_index] ) == XLAL_SUCCESS, XLAL_EFUNC );
485 XLAL_CHECK( queries->coh_index[query_index] < cache->coh_max_index, XLAL_EFAILED, "Coherent index %"LAL_UINT8_FORMAT" out of range [0,%"LAL_UINT8_FORMAT") at semicoherent index %"LAL_UINT8_FORMAT", query index %u", queries->coh_index[query_index], cache->coh_max_index, queries->semi_index, query_index );
486 XLAL_CHECK( queries->coh_left[query_index] <= queries->coh_right[query_index], XLAL_EINVAL );
487 XLAL_CHECK( queries->coh_left[query_index] <= queries->semi_left && queries->semi_right <= queries->coh_right[query_index], XLAL_EFAILED, "Range of coherent tiling [%i,%i] does not contain semicoherent tiling [%i,%i] at semicoherent index %"LAL_UINT8_FORMAT", query index %u", queries->coh_left[query_index], queries->coh_right[query_index], queries->semi_left, queries->semi_right, queries->semi_index, query_index );
488 }
489
490 // Make 'coh_index' a 1-based index, so zero can be used to indicate a missing query
491 ++queries->coh_index[query_index];
492
493 // Convert nearest coherent point to physical coordinates
494 XLAL_INIT_MEM( queries->coh_phys[query_index] );
495 XLAL_CHECK( XLALConvertSuperskyToPhysicalPoint( &queries->coh_phys[query_index], &coh_near_point_view.vector, &coh_point_view.vector, cache->coh_rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC );
496
497 // Compute the relevance of the current coherent frequency block:
498 // - Convert nearest coherent point to semicoherent reduced supersky coordinates
499 // - Relevance is nearest coherent point in semicoherent reduced supersky coordinates in dimension 'dim0', plus offset
500 {
501 double semi_near_point_array[cache->ndim];
502 gsl_vector_view semi_near_point_view = gsl_vector_view_array( semi_near_point_array, cache->ndim );
503 XLAL_CHECK( XLALConvertSuperskyToSuperskyPoint( &semi_near_point_view.vector, cache->semi_rssky_transf, &coh_near_point_view.vector, &coh_point_view.vector, cache->coh_rssky_transf ) == XLAL_SUCCESS, XLAL_EINVAL );
504 const double semi_near_point_dim0 = gsl_vector_get( &semi_near_point_view.vector, cache->dim0 );
505 queries->coh_relevance[query_index] = GSL_MAX( semi_near_point_dim0, queries->semi_rssky_dim0 ) + cache->coh_relevance_offset;
506 }
507
508 return XLAL_SUCCESS;
509
510}
511
512///
513/// Finalise a series of cache queries
514///
516 WeaveCacheQueries *queries,
517 PulsarDopplerParams *semi_phys,
518 UINT4 *semi_nfreqs
519)
520{
521
522 // Check input
523 XLAL_CHECK( queries != NULL, XLAL_EFAULT );
524 XLAL_CHECK( semi_phys != NULL, XLAL_EFAULT );
525 XLAL_CHECK( semi_nfreqs != NULL, XLAL_EFAULT );
526
527 // Check that every 'coh_index' is at least 1, i.e. a query was made
528 for ( size_t i = 0; i < queries->nqueries; ++i ) {
529 XLAL_CHECK( queries->coh_index[i] > 0, XLAL_EINVAL, "Missing query at index %zu", i );
530 }
531
532 // Compute the total number of points in the semicoherent frequency block
533 *semi_nfreqs = queries->semi_right - queries->semi_left + 1;
534
535 // Compute offsets to semicoherent left/right-most indexes to select each frequency partition
536 INT4 semi_part_left_offset = 0, semi_part_right_offset = 0;
537 XLAL_CHECK( cache_left_right_offsets( *semi_nfreqs, queries->nfreq_partitions, queries->freq_partition_index, &semi_part_left_offset, &semi_part_right_offset ) == XLAL_SUCCESS, XLAL_EFUNC );
538 XLAL_CHECK( queries->coh_part_left_offset[queries->freq_partition_index] <= semi_part_left_offset && semi_part_right_offset <= queries->coh_part_right_offset[queries->freq_partition_index], XLAL_EFAILED );
539
540 // Adjust semicoherent left/right-most indexes to select the given partition
541 // - If there are fewer points in the semicoherent frequency block than partitions,
542 // then some partitions will have 'semi_right' < 'semi_left', i.e. no points. In
543 // which set '*semi_nfreqs' to zero indicates that this partition should be skipped
544 // for this semicoherent frequency block
545 queries->semi_left += semi_part_left_offset;
546 queries->semi_right += semi_part_right_offset;
547 if ( queries->semi_right < queries->semi_left ) {
548 *semi_nfreqs = 0;
549 return XLAL_SUCCESS;
550 }
551
552 // Compute the total number of points in the semicoherent frequency block partition
553 *semi_nfreqs = queries->semi_right - queries->semi_left + 1;
554
555 // Adjust coherent left/right-most indexes to enclose the given partition
556 for ( size_t i = 0; i < queries->nqueries; ++i ) {
557 queries->coh_left[i] += queries->coh_part_left_offset[queries->freq_partition_index];
558 queries->coh_right[i] += queries->coh_part_right_offset[queries->freq_partition_index];
559 }
560
561 // Shift physical frequencies to first point in coherent/semicoherent frequency block partition
562 queries->semi_phys.fkdot[0] += queries->dfreq * queries->semi_left;
563 for ( size_t i = 0; i < queries->nqueries; ++i ) {
564 queries->coh_phys[i].fkdot[0] += queries->dfreq * queries->coh_left[i];
565 }
566
567 // Return first point in semicoherent frequency block partition
568 *semi_phys = queries->semi_phys;
569
570 // Increment number of semicoherent templates
571 queries->semi_ntmpl += *semi_nfreqs;
572
573 return XLAL_SUCCESS;
574
575}
576
577///
578/// Get number of computed coherent results, and number of coherent and semicoherent templates
579///
581 const WeaveCacheQueries *queries,
582 UINT8 *coh_nres,
583 UINT8 *coh_ntmpl,
584 UINT8 *semi_ntmpl
585)
586{
587
588 // Check input
589 XLAL_CHECK( queries != NULL, XLAL_EFAULT );
590 XLAL_CHECK( coh_nres != NULL, XLAL_EFAULT );
591 XLAL_CHECK( coh_ntmpl != NULL, XLAL_EFAULT );
592 XLAL_CHECK( semi_ntmpl != NULL, XLAL_EFAULT );
593
594 // Return number of computed coherent results
595 *coh_nres = 0;
596 for ( size_t i = 0; i < queries->nqueries; ++i ) {
597 *coh_nres += queries->coh_nres[i];
598 }
599
600 // Return number of computed coherent templates
601 *coh_ntmpl = 0;
602 for ( size_t i = 0; i < queries->nqueries; ++i ) {
603 *coh_ntmpl += queries->coh_ntmpl[i];
604 }
605
606 // Write number of semicoherent templates
607 *semi_ntmpl = queries->semi_ntmpl;
608
609 return XLAL_SUCCESS;
610
611}
612
613///
614/// Create a cache
615///
617 const LatticeTiling *coh_tiling,
618 const BOOLEAN interpolation,
619 const SuperskyTransformData *coh_rssky_transf,
620 const SuperskyTransformData *semi_rssky_transf,
621 WeaveCohInput *coh_input,
622 const UINT4 max_size,
623 const BOOLEAN all_gc
624)
625{
626
627 // Check input
628 XLAL_CHECK_NULL( coh_tiling != NULL, XLAL_EFAULT );
629 XLAL_CHECK_NULL( coh_input != NULL, XLAL_EFAULT );
630
631 // Allocate memory
632 WeaveCache *cache = XLALCalloc( 1, sizeof( *cache ) );
634
635 // Set fields
636 cache->coh_rssky_transf = coh_rssky_transf;
637 cache->semi_rssky_transf = semi_rssky_transf;
638 cache->coh_input = coh_input;
639 cache->generation = 0;
640
641 // Set garbage collection mode:
642 // - Garbage collection is not performed for a fixed-size cache (i.e. 'max_size > 0'),
643 // i.e. the cache will only discard items once the fixed-size cache is full, but not
644 // try to remove cache items earlier based on their relevances
645 // - Garbage collection is applied to as many items as possible if 'all_gc' is true
646 cache->any_gc = ( max_size == 0 );
647 cache->all_gc = all_gc;
648
649 // Get number of parameter-space dimensions
650 cache->ndim = XLALTotalLatticeTilingDimensions( coh_tiling );
652
653 // Get lowest tiled parameter-space dimension
654 if ( XLALTiledLatticeTilingDimensions( coh_tiling ) > 0 ) {
655 cache->dim0 = XLALLatticeTilingTiledDimension( coh_tiling, 0 );
656 } else {
657 cache->dim0 = 0;
658 }
660
661 // Compute offset used in computation of semicoherent point relevance:
662 {
663
664 // Convert a physical point far from any parameter-space boundaries to coherent and semicoherent reduced supersky coordinates
665 PulsarDopplerParams phys_origin = { .Alpha = 0, .Delta = LAL_PI_2, .fkdot = {0} };
666 XLAL_CHECK_NULL( XLALSetPhysicalPointSuperskyRefTime( &phys_origin, cache->coh_rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC );
667 double coh_origin_array[cache->ndim];
668 gsl_vector_view coh_origin_view = gsl_vector_view_array( coh_origin_array, cache->ndim );
669 XLAL_CHECK_NULL( XLALConvertPhysicalToSuperskyPoint( &coh_origin_view.vector, &phys_origin, cache->coh_rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC );
670 double semi_origin_array[cache->ndim];
671 gsl_vector_view semi_origin_view = gsl_vector_view_array( semi_origin_array, cache->ndim );
672 XLAL_CHECK_NULL( XLALConvertPhysicalToSuperskyPoint( &semi_origin_view.vector, &phys_origin, cache->semi_rssky_transf ) == XLAL_SUCCESS, XLAL_EFUNC );
673 const double semi_origin_dim0 = gsl_vector_get( &semi_origin_view.vector, cache->dim0 );
674
675 // Sample vertices of bounding box around 'coh_origin', and record maximum vertex in semicoherent reduced supersky coordinates in dimension 'dim0'
676 double coh_bbox_sample_array[cache->ndim];
677 gsl_vector_view coh_bbox_sample_view = gsl_vector_view_array( coh_bbox_sample_array, cache->ndim );
678 gsl_vector_memcpy( &coh_bbox_sample_view.vector, &coh_origin_view.vector );
679 double semi_bbox_sample_array[cache->ndim];
680 gsl_vector_view semi_bbox_sample_view = gsl_vector_view_array( semi_bbox_sample_array, cache->ndim );
681 double max_semi_bbox_sample_dim0 = semi_origin_dim0;
682 XLAL_CHECK_NULL( cache_max_semi_bbox_sample_dim0( cache, coh_tiling, 0, &coh_bbox_sample_view.vector, &semi_bbox_sample_view.vector, &max_semi_bbox_sample_dim0 ) == XLAL_SUCCESS, XLAL_EFUNC );
683
684 // Subtract off origin of 'semi_origin' to get relevance offset
685 cache->coh_relevance_offset = max_semi_bbox_sample_dim0 - semi_origin_dim0;
686
687 }
688
689 // If this is an interpolating search, create a lattice tiling locator
690 if ( interpolation ) {
691 cache->coh_locator = XLALCreateLatticeTilingLocator( coh_tiling );
692 XLAL_CHECK_NULL( cache->coh_locator != NULL, XLAL_EFUNC );
693 const LatticeTilingStats *stats = XLALLatticeTilingStatistics( coh_tiling, cache->ndim - 2 );
694 XLAL_CHECK_NULL( stats != NULL, XLAL_EFUNC );
695 cache->coh_max_index = stats->total_points;
696 }
697
698 // Create a heap which sorts items by "relevance", a quantity which determines how long
699 // cache items are kept. Consider the following scenario:
700 //
701 // +-----> parameter-space dimension 'dim0'
702 // |
703 // V parameter-space dimensions > 'dim0'
704 //
705 // :
706 // : R[S1] = relevance of semicoherent point 'S1'
707 // :
708 // +-----+
709 // | /`\ |
710 // || S1||
711 // | \,/ |
712 // +-----+
713 // + :
714 // / \ : R[S2] = relevance of semicoherent point 'S2'
715 // /,,,\ :
716 // /( \\ +-----+
717 // + ( \\ | /`\ |
718 // \\ C \\ || S2||
719 // \\ ) + | \,/ |
720 // \\ )/: +-----+
721 // \```/ :
722 // \ / :
723 // + : R[C] = relevance of coherent point 'C'
724 // :
725 //
726 // The relevance R[C] of the coherent point 'C' is given by the coordinate in dimension 'dim0' of
727 // the *rightmost* edge of the bounding box surrounding its metric ellipse. The relevances of
728 // two semicoherent points S1 and S2, R[S1] and R[S2], are given by the *leftmost* edges of the
729 // bounding box surrounding their metric ellipses.
730 //
731 // Note that iteration over the parameter space is ordered such that dimension 'dim0' is the slowest
732 // (tiled) coordinate, i.e. dimension 'dim0' is passed over only once, therefore coordinates in this
733 // dimension are monotonically increasing, therefore relevances are also monotonically increasing.
734 //
735 // Suppose S1 is the current point in the semicoherent parameter-space tiling; note that R[C] > R[S1].
736 // It is clear that, as iteration progresses, some future semicoherent points will overlap with C.
737 // Therefore C cannot be discarded from the cache, since it will be the closest point for future
738 // semicoherent points. Now suppose that S2 is the current point; note that R[C] < R[S1]. It is clear
739 // that neither S2, nor any future point in the semicoherent parameter-space tiling, can ever overlap
740 // with C. Therefore C can never be the closest point for any future semicoherent points, and therefore
741 // it can safely be discarded from the cache.
742 //
743 // In short, an item in the cache can be discarded once its relevance falls below the threshold set
744 // by the current point semicoherent in the semicoherent parameter-space tiling.
745 //
746 // Items removed from the heap are destroyed by calling cache_item_destroy().
748 XLAL_CHECK_NULL( cache->relevance_heap != NULL, XLAL_EFUNC );
749
750 // Create a hash table which looks up cache items by partition and locator index. Items removed
751 // from the hash table are NOT destroyed, since items are shared with 'relevance_heap'.
753 XLAL_CHECK_NULL( cache->coh_index_hash != NULL, XLAL_EFUNC );
754
755 // Create a bitset which records which cache items have ever been computed.
756 cache->coh_computed_bitset = XLALBitsetCreate();
757 XLAL_CHECK_NULL( cache->coh_computed_bitset != NULL, XLAL_EFUNC );
758
759 return cache;
760
761}
762
763///
764/// Destroy a cache
765///
767 WeaveCache *cache
768)
769{
770 if ( cache != NULL ) {
772 XLALHeapDestroy( cache->relevance_heap );
773 XLALHashTblDestroy( cache->coh_index_hash );
774 cache_item_destroy( cache->saved_item );
775 XLALBitsetDestroy( cache->coh_computed_bitset );
776 XLALFree( cache );
777 }
778}
779
780///
781/// Determine the mean maximum size obtained by caches
782///
784 REAL4 *cache_mean_max_size,
785 const size_t ncache,
786 WeaveCache *const *cache
787)
788{
789
790 // Check input
791 XLAL_CHECK( cache_mean_max_size != NULL, XLAL_EFAULT );
792 XLAL_CHECK( ncache > 0, XLAL_ESIZE );
793 XLAL_CHECK( cache != NULL, XLAL_EFAULT );
794
795 // Determine the mean maximum size obtained by caches
796 *cache_mean_max_size = 0;
797 for ( size_t i = 0; i < ncache; ++i ) {
798 *cache_mean_max_size += cache[i]->heap_max_size;
799 }
800 *cache_mean_max_size /= ncache;
801
802 return XLAL_SUCCESS;
803
804}
805
806///
807/// Write various information from caches to a FITS file
808///
810 FITSFile *file,
811 const size_t ncache,
812 WeaveCache *const *cache
813)
814{
815
816 // Check input
817 XLAL_CHECK( file != NULL, XLAL_EFAULT );
818 XLAL_CHECK( ncache > 0, XLAL_ESIZE );
819 XLAL_CHECK( cache != NULL, XLAL_EFAULT );
820
821 // Write the mean maximum size obtained by caches
822 REAL4 cache_mean_max_size = 0;
823 XLAL_CHECK( XLALWeaveGetCacheMeanMaxSize( &cache_mean_max_size, ncache, cache ) == XLAL_SUCCESS, XLAL_EFUNC );
824 XLAL_CHECK( XLALFITSHeaderWriteREAL4( file, "cachemmx", cache_mean_max_size, "Mean maximum size obtained by cache" ) == XLAL_SUCCESS, XLAL_EFUNC );
825
826 return XLAL_SUCCESS;
827
828}
829
830///
831/// Expire all items in the cache
832///
834 WeaveCache *cache
835)
836{
837
838 // Check input
839 XLAL_CHECK( cache != NULL, XLAL_EFAULT );
840
841 // Advance current generation of cache items
842 // - Existing items will no longer be accessible, but are still kept for reuse
843 ++cache->generation;
844
845 return XLAL_SUCCESS;
846
847}
848
849///
850/// Clear all items in the cache from memory
851///
853 WeaveCache *cache
854)
855{
856
857 // Check input
858 XLAL_CHECK( cache != NULL, XLAL_EFAULT );
859
860 // Clear items in the relevance heap and hash table from memory
861 XLAL_CHECK( XLALHeapClear( cache->relevance_heap ) == XLAL_SUCCESS, XLAL_EFUNC );
862 XLAL_CHECK( XLALHashTblClear( cache->coh_index_hash ) == XLAL_SUCCESS, XLAL_EFUNC );
863
864 // Reset current generation of cache items
865 cache->generation = 0;
866
867 return XLAL_SUCCESS;
868
869}
870
871///
872/// Retrieve coherent results for a given query, or compute new coherent results if not found
873///
875 WeaveCache *cache,
876 const WeaveCacheQueries *queries,
877 const UINT4 query_index,
878 const WeaveCohResults **coh_res,
879 UINT8 *coh_index,
880 UINT4 *coh_offset,
881 WeaveSearchTiming *tim
882)
883{
884
885 // Check input
886 XLAL_CHECK( cache != NULL, XLAL_EFAULT );
887 XLAL_CHECK( queries != NULL, XLAL_EFAULT );
888 XLAL_CHECK( query_index < queries->nqueries, XLAL_EINVAL );
889 XLAL_CHECK( coh_res != NULL, XLAL_EFAULT );
890 XLAL_CHECK( coh_offset != NULL, XLAL_EFAULT );
891 XLAL_CHECK( tim != NULL, XLAL_EFAULT );
892
893 // See if coherent results are already cached
894 const cache_item find_key = { .generation = cache->generation, .coh_index = queries->coh_index[query_index] };
895 const cache_item *find_item = NULL;
896 XLAL_CHECK( XLALHashTblFind( cache->coh_index_hash, &find_key, ( const void ** ) &find_item ) == XLAL_SUCCESS, XLAL_EFUNC );
897 if ( find_item == NULL ) {
898
899 // Reuse 'saved_item' if possible, otherwise allocate memory for a new cache item
900 if ( cache->saved_item == NULL ) {
901 cache->saved_item = XLALCalloc( 1, sizeof( *cache->saved_item ) );
902 XLAL_CHECK( cache->saved_item != NULL, XLAL_EINVAL );
903 }
904 cache_item *new_item = cache->saved_item;
905 find_item = new_item;
906
907 // Set the key of the new cache item for future lookups
908 new_item->generation = find_key.generation;
909 new_item->coh_index = find_key.coh_index;
910
911 // Set the relevance of the coherent frequency block associated with the new cache item
912 new_item->relevance = queries->coh_relevance[query_index];
913
914 // Determine the number of points in the coherent frequency block
915 const UINT4 coh_nfreqs = queries->coh_right[query_index] - queries->coh_left[query_index] + 1;
916
917 // Compute coherent results for the new cache item
918 XLAL_CHECK( XLALWeaveCohResultsCompute( &new_item->coh_res, cache->coh_input, &queries->coh_phys[query_index], coh_nfreqs, tim ) == XLAL_SUCCESS, XLAL_EFUNC );
919
920 // Add new cache item to the index hash table
921 XLAL_CHECK( XLALHashTblAdd( cache->coh_index_hash, new_item ) == XLAL_SUCCESS, XLAL_EFUNC );
922
923 // Get the item in the cache with the smallest relevance
924 const cache_item *least_relevant_item = ( const cache_item * ) XLALHeapRoot( cache->relevance_heap );
926
927 // Create a 'fake' item specifying thresholds for cache item relevance, for comparison with 'least_relevant_item'
928 const cache_item relevance_threshold = { .generation = cache->generation, .relevance = queries->semi_relevance };
929
930 // If garbage collection is enabled, and item's relevance has fallen below the threshold relevance, it can be removed from the cache
931 if ( cache->any_gc && least_relevant_item != NULL && least_relevant_item != new_item && cache_item_compare_by_relevance( least_relevant_item, &relevance_threshold ) < 0 ) {
932
933 // Remove least relevant item from index hash table
934 XLAL_CHECK( XLALHashTblRemove( cache->coh_index_hash, least_relevant_item ) == XLAL_SUCCESS, XLAL_EFUNC );
935
936 // Exchange 'saved_item' with the least relevant item in the relevance heap
937 XLAL_CHECK( XLALHeapExchangeRoot( cache->relevance_heap, ( void ** ) &cache->saved_item ) == XLAL_SUCCESS, XLAL_EFUNC );
938
939 // If maximal garbage collection is enabled, remove as many results as possible
940 while ( cache->all_gc ) {
941
942 // Get the item in the cache with the smallest relevance
943 least_relevant_item = ( const cache_item * ) XLALHeapRoot( cache->relevance_heap );
945
946 // If item's relevance has fallen below the threshold relevance, it can be removed from the cache
947 if ( least_relevant_item != NULL && least_relevant_item != new_item && cache_item_compare_by_relevance( least_relevant_item, &relevance_threshold ) < 0 ) {
948
949 // Remove least relevant item from index hash table
950 XLAL_CHECK( XLALHashTblRemove( cache->coh_index_hash, least_relevant_item ) == XLAL_SUCCESS, XLAL_EFUNC );
951
952 // Remove and destroy least relevant item from the relevance heap
954
955 } else {
956
957 // All cache items are still relevant
958 break;
959
960 }
961
962 }
963
964 } else {
965
966 // Add new cache item to the relevance heap; 'saved_item' many now contains an item removed from the heap
967 XLAL_CHECK( XLALHeapAdd( cache->relevance_heap, ( void ** ) &cache->saved_item ) == XLAL_SUCCESS, XLAL_EFUNC );
968
969 // If 'saved_item' contains an item removed from the heap, also remove it from the index hash table
970 if ( cache->saved_item != NULL ) {
971 XLAL_CHECK( XLALHashTblRemove( cache->coh_index_hash, cache->saved_item ) == XLAL_SUCCESS, XLAL_EFUNC );
972 }
973
974 }
975
976 // Update maximum size obtained by relevance heap
977 const UINT4 heap_size = XLALHeapSize( cache->relevance_heap );
978 if ( cache->heap_max_size < heap_size ) {
979 cache->heap_max_size = heap_size;
980 }
981
982 // Increment number of computed coherent results
983 queries->coh_nres[query_index] += coh_nfreqs;
984
985 // Check if coherent results have been computed previously
986 const UINT8 coh_bitset_index = queries->freq_partition_index * cache->coh_max_index + find_key.coh_index;
987 BOOLEAN computed = 0;
988 XLAL_CHECK( XLALBitsetGet( cache->coh_computed_bitset, coh_bitset_index, &computed ) == XLAL_SUCCESS, XLAL_EFUNC );
989 if ( !computed ) {
990
991 // Coherent results have not been computed before: increment the number of coherent templates
992 queries->coh_ntmpl[query_index] += coh_nfreqs;
993
994 // This coherent result has now been computed
995 XLAL_CHECK( XLALBitsetSet( cache->coh_computed_bitset, coh_bitset_index, 1 ) == XLAL_SUCCESS, XLAL_EFUNC );
996
997 }
998
999 }
1000
1001 // Return coherent results from cache
1002 *coh_res = find_item->coh_res;
1003
1004 // Return index of coherent result
1005 *coh_index = find_item->coh_index;
1006
1007 // Return offset at which coherent results should be combined with semicoherent results
1008 *coh_offset = queries->semi_left - queries->coh_left[query_index];
1009
1010 return XLAL_SUCCESS;
1011
1012}
1013
1014// Local Variables:
1015// c-file-style: "linux"
1016// c-basic-offset: 2
1017// End:
static int cache_item_compare_by_coh_index(const void *x, const void *y)
Compare cache items by generation, then locator index.
Definition: CacheResults.c:186
WeaveCache * XLALWeaveCacheCreate(const LatticeTiling *coh_tiling, const BOOLEAN interpolation, const SuperskyTransformData *coh_rssky_transf, const SuperskyTransformData *semi_rssky_transf, WeaveCohInput *coh_input, const UINT4 max_size, const BOOLEAN all_gc)
Create a cache.
Definition: CacheResults.c:616
void XLALWeaveCacheQueriesDestroy(WeaveCacheQueries *queries)
Destroy storage for a series of cache queries.
Definition: CacheResults.c:383
int XLALWeaveCacheQuery(const WeaveCache *cache, WeaveCacheQueries *queries, const UINT4 query_index)
Query a cache for the results nearest to a given coherent point.
Definition: CacheResults.c:449
int XLALWeaveCacheQueriesFinal(WeaveCacheQueries *queries, PulsarDopplerParams *semi_phys, UINT4 *semi_nfreqs)
Finalise a series of cache queries.
Definition: CacheResults.c:515
int XLALWeaveCacheQueriesInit(WeaveCacheQueries *queries, const UINT8 semi_index, const gsl_vector *semi_rssky, const INT4 semi_left, const INT4 semi_right, const UINT4 freq_partition_index)
Initialise a series of cache queries.
Definition: CacheResults.c:404
int XLALWeaveCacheExpire(WeaveCache *cache)
Expire all items in the cache.
Definition: CacheResults.c:833
int XLALWeaveGetCacheMeanMaxSize(REAL4 *cache_mean_max_size, const size_t ncache, WeaveCache *const *cache)
Determine the mean maximum size obtained by caches.
Definition: CacheResults.c:783
static int cache_left_right_offsets(const UINT4 semi_nfreqs, const UINT4 nfreq_partitions, const UINT4 freq_partition_index, INT4 *left_offset, INT4 *right_offset)
Compute left/right-most index offsets to select a given partition.
Definition: CacheResults.c:261
void XLALWeaveCacheDestroy(WeaveCache *cache)
Destroy a cache.
Definition: CacheResults.c:766
#define COMPARE_BY(x, y)
Definition: CacheResults.c:32
int XLALWeaveCacheRetrieve(WeaveCache *cache, const WeaveCacheQueries *queries, const UINT4 query_index, const WeaveCohResults **coh_res, UINT8 *coh_index, UINT4 *coh_offset, WeaveSearchTiming *tim)
Retrieve coherent results for a given query, or compute new coherent results if not found.
Definition: CacheResults.c:874
WeaveCacheQueries * XLALWeaveCacheQueriesCreate(const LatticeTiling *semi_tiling, const SuperskyTransformData *semi_rssky_transf, const double dfreq, const UINT4 nqueries, const UINT4 nfreq_partitions)
Create storage for a series of cache queries.
Definition: CacheResults.c:305
int XLALWeaveCacheQueriesGetCounts(const WeaveCacheQueries *queries, UINT8 *coh_nres, UINT8 *coh_ntmpl, UINT8 *semi_ntmpl)
Get number of computed coherent results, and number of coherent and semicoherent templates.
Definition: CacheResults.c:580
int XLALWeaveCacheClear(WeaveCache *cache)
Clear all items in the cache from memory.
Definition: CacheResults.c:852
static void cache_item_destroy(void *x)
Destroy a cache item.
Definition: CacheResults.c:157
static int cache_item_compare_by_relevance(const void *x, const void *y)
Compare cache items by generation, then relevance.
Definition: CacheResults.c:171
int XLALWeaveCacheWriteInfo(FITSFile *file, const size_t ncache, WeaveCache *const *cache)
Write various information from caches to a FITS file.
Definition: CacheResults.c:809
static UINT8 cache_item_hash(const void *x)
Hash cache items by generation and locator index.
Definition: CacheResults.c:201
static int cache_max_semi_bbox_sample_dim0(const WeaveCache *cache, const LatticeTiling *coh_tiling, const size_t i, gsl_vector *coh_bbox_sample, gsl_vector *semi_bbox_sample, double *max_semi_bbox_sample_dim0)
Sample points on surface of coherent bounding box, convert to semicoherent supersky coordinates,...
Definition: CacheResults.c:216
Module which caches computed coherent results.
void XLALWeaveCohResultsDestroy(WeaveCohResults *coh_res)
Destroy coherent results.
int XLALWeaveCohResultsCompute(WeaveCohResults **coh_res, WeaveCohInput *coh_input, const PulsarDopplerParams *coh_phys, const UINT4 coh_nfreqs, WeaveSearchTiming *tim)
Create and compute coherent results.
int XLALFITSHeaderWriteREAL4(FITSFile UNUSED *file, const CHAR UNUSED *key, const REAL4 UNUSED value, const CHAR UNUSED *comment)
Definition: FITSFileIO.c:1089
struct tagFITSFile FITSFile
Representation of a FITS file.
Definition: FITSFileIO.h:54
LALBitset * XLALBitsetCreate(void)
void XLALBitsetDestroy(LALBitset *bs)
int XLALBitsetGet(const LALBitset *bs, const UINT8 idx, BOOLEAN *is_set)
int XLALBitsetSet(LALBitset *bs, const UINT8 idx, const BOOLEAN is_set)
#define LAL_PI_2
unsigned char BOOLEAN
#define XLAL_INIT_MEM(x)
uint64_t UINT8
uint32_t UINT4
int32_t INT4
float REAL4
int XLALPearsonHash(void *hval, const size_t hval_len, const void *data, const size_t data_len)
int XLALHashTblFind(const LALHashTbl *ht, const void *x, const void **y)
int XLALHashTblAdd(LALHashTbl *ht, void *x)
int XLALHashTblRemove(LALHashTbl *ht, const void *x)
LALHashTbl * XLALHashTblCreate(LALHashTblDtorFcn dtor, LALHashTblHashFcn hash, LALHashTblCmpFcn cmp)
void XLALHashTblDestroy(LALHashTbl *ht)
int XLALHashTblClear(LALHashTbl *ht)
int XLALHeapAdd(LALHeap *h, void **x)
LALHeap * XLALHeapCreate(LALHeapDtorFcn dtor, int max_size, int min_or_max_heap, LALHeapCmpFcn cmp)
int XLALHeapSize(const LALHeap *h)
int XLALHeapExchangeRoot(LALHeap *h, void **x)
const void * XLALHeapRoot(const LALHeap *h)
int XLALHeapRemoveRoot(LALHeap *h)
int XLALHeapClear(LALHeap *h)
void XLALHeapDestroy(LALHeap *h)
void * XLALCalloc(size_t m, size_t n)
void XLALFree(void *p)
#define LAL_UINT8_FORMAT
size_t XLALTotalLatticeTilingDimensions(const LatticeTiling *tiling)
Return the total number of dimensions of the lattice tiling.
int XLALNearestLatticeTilingBlock(const LatticeTilingLocator *loc, const gsl_vector *point, const size_t dim, gsl_vector *nearest_point, UINT8 *nearest_index, INT4 *nearest_left, INT4 *nearest_right)
Locate the nearest block in a lattice tiling to a given point.
void XLALDestroyLatticeTilingLocator(LatticeTilingLocator *loc)
Destroy a lattice tiling locator.
size_t XLALTiledLatticeTilingDimensions(const LatticeTiling *tiling)
Return the number of tiled dimensions of the lattice tiling.
size_t XLALLatticeTilingTiledDimension(const LatticeTiling *tiling, const size_t tiled_dim)
Return the dimension of the tiled lattice tiling dimension indexed by 'tiled_dim'.
const LatticeTilingStats * XLALLatticeTilingStatistics(const LatticeTiling *tiling, const size_t dim)
Return statistics related to the number/value of lattice tiling points in a dimension.
LatticeTilingLocator * XLALCreateLatticeTilingLocator(const LatticeTiling *tiling)
Create a new lattice tiling locator.
REAL8 XLALLatticeTilingBoundingBox(const LatticeTiling *tiling, const size_t dim)
Return the bounding box extent of the lattice tiling in a given dimension, or 0 for non-tiled dimensi...
int XLALSetPhysicalPointSuperskyRefTime(PulsarDopplerParams *out_phys, const SuperskyTransformData *rssky_transf)
Set the reference time of a physical point to that of the reduced supersky coordinates.
int XLALConvertPhysicalToSuperskyPoint(gsl_vector *out_rssky, const PulsarDopplerParams *in_phys, const SuperskyTransformData *rssky_transf)
Convert a point from physical to supersky coordinates.
int XLALConvertSuperskyToPhysicalPoint(PulsarDopplerParams *out_phys, const gsl_vector *in_rssky, const gsl_vector *ref_rssky, const SuperskyTransformData *rssky_transf)
Convert a point from supersky to physical coordinates.
int XLALConvertSuperskyToSuperskyPoint(gsl_vector *out_rssky, const SuperskyTransformData *out_rssky_transf, const gsl_vector *in_rssky, const gsl_vector *ref_rssky, const SuperskyTransformData *in_rssky_transf)
Convert a point between supersky coordinates.
#define xlalErrno
#define XLAL_CHECK(assertion,...)
#define XLAL_CHECK_NULL(assertion,...)
XLAL_ENOMEM
XLAL_SUCCESS
XLAL_EFAULT
XLAL_EFUNC
XLAL_EDOM
XLAL_ESIZE
XLAL_EINVAL
XLAL_EFAILED
list y
Statistics related to the number/value of lattice tiling points in a dimension.
Type containing the 'Doppler-parameters' affecting the time-evolution of the phase.
REAL8 Alpha
Sky position: RA (longitude) in equatorial coords and radians.
Item stored in the cache.
Definition: CacheResults.c:37
REAL4 relevance
Relevance, used to decide how long to keep items.
Definition: CacheResults.c:41
UINT8 coh_index
Coherent locator index, used to find items in cache.
Definition: CacheResults.c:43
UINT4 generation
Generation, used both to find items in cache and to decide how long to keep items.
Definition: CacheResults.c:39
WeaveCohResults * coh_res
Results of a coherent computation on a single segment.
Definition: CacheResults.c:45
Cache used to store coherent results.
Definition: CacheResults.c:105
UINT8 coh_max_index
Maximum value of index from coherent locator.
Definition: CacheResults.c:119
double coh_relevance_offset
Offset used in computation of coherent point relevance.
Definition: CacheResults.c:131
size_t ndim
Number of parameter-space dimensions.
Definition: CacheResults.c:107
size_t dim0
Lowest tiled parameter-space dimension.
Definition: CacheResults.c:109
LatticeTilingLocator * coh_locator
Coherent parameter-space tiling locator.
Definition: CacheResults.c:117
WeaveCohInput * coh_input
Input data required for computing coherent results.
Definition: CacheResults.c:115
UINT4 generation
Current generation of cache items.
Definition: CacheResults.c:121
LALHashTbl * coh_index_hash
Hash table which looks up cache items by index.
Definition: CacheResults.c:127
BOOLEAN all_gc
Whether garbage collection should remove as many results as possible.
Definition: CacheResults.c:135
LALBitset * coh_computed_bitset
Bitset which records whether an item has ever been computed.
Definition: CacheResults.c:129
const SuperskyTransformData * semi_rssky_transf
Reduced supersky transform data for semicoherent lattice.
Definition: CacheResults.c:113
UINT4 heap_max_size
Maximum size obtained by relevance heap.
Definition: CacheResults.c:125
cache_item * saved_item
Save an no-longer-used cache item for re-use.
Definition: CacheResults.c:137
const SuperskyTransformData * coh_rssky_transf
Reduced supersky transform data for coherent lattice.
Definition: CacheResults.c:111
BOOLEAN any_gc
Whether any garbage collection of results should be used.
Definition: CacheResults.c:133
LALHeap * relevance_heap
Heap which ranks cache items by relevance.
Definition: CacheResults.c:123
Container for a series of cache queries.
Definition: CacheResults.c:51
UINT4 freq_partition_index
Index to current partition of semicoherent frequency block.
Definition: CacheResults.c:63
UINT8 semi_index
Sequential index for the current semicoherent frequency block.
Definition: CacheResults.c:85
INT4 * coh_part_right_offset
Offset to apply to coherent right-most index to enclose a frequency partition.
Definition: CacheResults.c:67
REAL4 semi_relevance
Relevance of the current semicoherent frequency block.
Definition: CacheResults.c:95
UINT8 * coh_nres
Number of computed coherent results (per query)
Definition: CacheResults.c:79
UINT8 semi_ntmpl
Number of semicoherent templates (over all queries)
Definition: CacheResults.c:99
PulsarDopplerParams * coh_phys
Physical points of each queried coherent frequency block.
Definition: CacheResults.c:71
size_t dim0
Lowest tiled parameter-space dimension.
Definition: CacheResults.c:55
UINT4 nfreq_partitions
Number of partitions to divide semicoherent frequency block into.
Definition: CacheResults.c:61
INT4 * coh_right
Indexes of right-most point in queried coherent frequency block.
Definition: CacheResults.c:75
UINT4 nqueries
Number of queries for which space is allocated.
Definition: CacheResults.c:59
INT4 semi_right
Index of right-most point in current semicoherent frequency block.
Definition: CacheResults.c:93
UINT8 * coh_ntmpl
Number of coherent templates (per query)
Definition: CacheResults.c:81
size_t ndim
Number of parameter-space dimensions.
Definition: CacheResults.c:53
const SuperskyTransformData * semi_rssky_transf
Reduced supersky transform data for semicoherent lattice.
Definition: CacheResults.c:83
INT4 * coh_part_left_offset
Offset to apply to coherent left-most index to enclose a frequency partition.
Definition: CacheResults.c:65
double semi_relevance_offset
Offset used in computation of semicoherent point relevance.
Definition: CacheResults.c:97
UINT8 * coh_index
Sequential indexes for each queried coherent frequency block.
Definition: CacheResults.c:69
PulsarDopplerParams semi_phys
Physical coordinates of the current semicoherent frequency block.
Definition: CacheResults.c:89
INT4 * coh_left
Indexes of left-most point in queried coherent frequency block.
Definition: CacheResults.c:73
REAL4 * coh_relevance
Relevance of each queried coherent frequency block.
Definition: CacheResults.c:77
INT4 semi_left
Index of left-most point in current semicoherent frequency block.
Definition: CacheResults.c:91