libftsh
A Fast Transform for Spherical Harmonics
|
00001 /* 00002 * Copyright (c) 2000, 2012 Martin J. Mohlenkamp 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 * 00018 */ 00019 00020 00027 /* make sure we haven't already included this library **/ 00028 #ifndef LIBFTSH_PRESENT 00029 #define LIBFTSH_PRESENT 00030 00031 00032 #include <math.h> 00033 #include <stdlib.h> 00034 #include <stdio.h> 00035 #include <assert.h> 00036 #include <string.h> 00037 #include <time.h> 00038 00039 00040 #ifndef PI 00041 #define PI 3.14159265358979323846264338328 00042 #endif 00043 00048 #ifndef USE_double 00049 #define USE_double 1 00050 #endif 00051 00053 #if USE_double 00054 #define REAL double 00055 #else 00056 #define REAL float 00057 #endif 00058 00059 /* Deal with possible ways fftw was compiled */ 00060 #if 0 00061 00062 #if USE_double 00063 /* double precision header */ 00064 #include "dfftw.h" 00065 #include "drfftw.h" 00066 #else 00067 /* single precision header */ 00068 #include "sfftw.h" 00069 #include "srfftw.h" 00070 #endif 00071 #else /*fftw in only one precision. pray it is the right precision */ 00072 /* Make sure it is compiled with fftw_real == REAL */ 00073 #include "fftw.h" 00074 #include "rfftw.h" 00075 #endif 00076 00077 /*************************************************************************/ 00078 /**** data structures ****************************************************/ 00079 /*************************************************************************/ 00080 00081 00095 typedef struct{ 00097 int numpts; 00099 fftw_complex *complex_work; 00101 fftw_plan w_plan; 00103 rfftw_plan rw_plan_forward; 00105 rfftw_plan rw_plan_reverse; 00107 REAL *trig_save; 00108 }Ftrigtw_Plan; 00109 00112 typedef struct 00113 { 00119 int max_size; 00121 int n_row; 00123 int n_col; 00127 REAL *matrix; 00128 } Dense_Matrix; 00129 00135 typedef struct 00136 { 00142 int max_size; 00146 int n_row; 00148 REAL *vector; 00149 } Dense_Vector; 00150 00162 typedef struct 00163 { 00169 int max_size; 00173 int max_rows; 00177 int max_bands; 00179 int n_row; 00181 int n_col; 00183 int non_zero; 00193 int *band_p; 00204 int *band_list; 00206 REAL *matrix; 00207 } Banded_Matrix; 00208 00224 typedef struct{ 00226 unsigned int max_size; 00228 int *int_work; 00230 REAL *real_work; 00231 } Bdmat_Op_Workspace; 00232 00241 typedef struct{ 00245 int best_level; 00247 int num_levels; 00256 unsigned short int **branching; 00258 unsigned int **cost_full; 00263 unsigned int **cost_asym; 00267 unsigned int *order_level; 00272 unsigned int *order_within; 00273 }Dyadic_Gsearch_Save; 00274 00286 typedef struct{ 00288 int bell_length; 00302 int *bell_offsets; 00304 REAL *bell_handle; 00305 }Fast1_Save; 00306 00317 typedef struct{ 00321 int numpts; 00323 int left_extra; 00325 int right_extra; 00330 int fcn_offset; 00336 int coef_offset; 00340 REAL *bell; 00346 REAL *dualbell; 00355 int which_transform; 00359 Ftrigtw_Plan transform_plan; 00360 }Local_Trig_Interval; 00361 00367 typedef struct{ 00373 int max_intervals; 00375 int n_interval[2]; 00378 Banded_Matrix matrix[2]; 00382 Local_Trig_Interval *ilist[2]; 00383 }Pm_1D; 00384 00391 typedef struct{ 00396 Banded_Matrix matrix[2]; 00397 }Pm_Direct_bd; 00398 00403 typedef struct{ 00407 Dense_Matrix matrix[2]; 00408 }Pm_Direct_d; 00409 00422 typedef struct{ 00425 int numpts; 00428 int band_limit; 00431 Dense_Vector dvect_coef[2]; 00433 Dense_Vector dvect_fcn[2]; 00435 REAL *eval_fcn[2]; 00437 REAL *over_rootsin; 00439 REAL *mod_weight; 00440 }Pm_1D_Workspace; 00441 00442 00445 typedef struct{ 00450 int numpts; 00454 REAL **sofar; 00458 int *size; 00461 REAL *ex; 00464 REAL *why; 00465 }Pmncos_Recurrence_Save; 00466 00467 /*************************************************************************/ 00468 /******* END Data Structures *********************************************/ 00469 /*************************************************************************/ 00470 00471 00472 /*************************************************************************/ 00473 /******* BEGIN function prototypes ***************************************/ 00474 /*************************************************************************/ 00475 00476 /* dvect.c */ 00477 Dense_Vector init_dvect_memory(unsigned int n 00478 ); 00479 void give_dvect_memory(Dense_Vector *current, 00480 Dense_Vector *previous 00481 ); 00482 /* dmat.c */ 00483 Dense_Matrix init_dmat_memory(unsigned int n 00484 ); 00485 void give_dmat_memory(Dense_Matrix *current, 00486 Dense_Matrix *previous 00487 ); 00488 void free_dmat_memory(Dense_Matrix *in 00489 ); 00490 void dump_bin_dmat(Dense_Matrix *x, 00491 FILE *out 00492 ); 00493 void load_bin_dmat(Dense_Matrix *x, 00494 FILE *in 00495 ); 00496 /* dmat_ops.c */ 00497 void dmat_dvect_multiply(Dense_Vector *out, 00498 Dense_Matrix *inmat, 00499 Dense_Vector *invect 00500 ); 00501 void dmat_t_dvect_multiply(Dense_Vector *out, 00502 Dense_Matrix *inmat, 00503 Dense_Vector *invect 00504 ); 00505 /* bdmat.c */ 00506 Banded_Matrix init_bdmat_memory(int max_size, 00507 int max_rows, 00508 int max_bands 00509 ); 00510 void give_bdmat_memory(Banded_Matrix *current, 00511 Banded_Matrix *previous 00512 ); 00513 void free_bdmat_memory(Banded_Matrix *in 00514 ); 00515 void bdmat_copy(Banded_Matrix *out, 00516 Banded_Matrix *in 00517 ); 00518 void dump_bin_bdmat(Banded_Matrix *x, 00519 FILE *out 00520 ); 00521 void load_bin_bdmat(Banded_Matrix *x, 00522 FILE *in 00523 ); 00524 /* bdmat_ops.c */ 00525 void bdmat_dvect_multiply(Dense_Vector *out, 00526 Banded_Matrix *inmat, 00527 Dense_Vector *invect 00528 ); 00529 void bdmat_t_dvect_multiply(Dense_Vector *out, 00530 Banded_Matrix *inmat, 00531 Dense_Vector *invect 00532 ); 00533 void dmat_to_bdmat(Banded_Matrix *out, 00534 Dense_Matrix *in, 00535 REAL cutoff, 00536 int min_gap 00537 ); 00538 /* dyadic_gsearch.c */ 00539 int dyadic_gsearch(Dyadic_Gsearch_Save *dy_gs_save 00540 ); 00541 void dyadic_gsearch_init(Dyadic_Gsearch_Save *dy_gs_save, 00542 int num_levels 00543 ); 00544 void dyadic_gsearch_free(Dyadic_Gsearch_Save *dy_gs_save 00545 ); 00546 /* fast1_fromfile.c*/ 00547 void fast1_fromfile(int *numpts_ptr, 00548 int *band_limit_ptr, 00549 REAL **node_ptr, 00550 REAL **weight_ptr, 00551 Pm_1D **pmn_matrix_ptr, 00552 Pm_1D_Workspace *pmnwork, 00553 FILE *fp 00554 ); 00555 void load_fast1(int *numpts_ptr, 00556 int *band_limit_ptr, 00557 int *num_levels_ptr, 00558 REAL **node_ptr, 00559 REAL **weight_ptr, 00560 Fast1_Save *saves_fordump, 00561 Pm_1D **pmn_matrix_ptr, 00562 FILE *fp 00563 ); 00564 /* direct1_fromfile.c*/ 00565 void direct1_fromfile(int *numpts_ptr, 00566 int *band_limit_ptr, 00567 REAL **node_ptr, 00568 REAL **weight_ptr, 00569 Pm_Direct_d **pmn_matrix_ptr, 00570 Pm_1D_Workspace *pmnwork, 00571 FILE *fp 00572 ); 00573 void load_direct1(int *numpts_ptr, 00574 int *band_limit_ptr, 00575 REAL **node_ptr, 00576 REAL **weight_ptr, 00577 Pm_Direct_d **pmn_matrix_ptr, 00578 FILE *fp 00579 ); 00580 /* dctw.c */ 00581 void dctw(REAL *fcn, 00582 Ftrigtw_Plan *main_plan, 00583 int dir 00584 ); 00585 void dctw_init(Ftrigtw_Plan *main_plan, 00586 int flags, 00587 int numpts 00588 ); 00589 void rfftw_to_NR_format(REAL *data_nr, 00590 REAL *data_rfftw, 00591 int numpts, 00592 int dir 00593 ); 00594 /* lctw.c */ 00595 void lctw(REAL *fcn, 00596 Ftrigtw_Plan *main_plan 00597 ); 00598 void lctw_init(Ftrigtw_Plan *main_plan, 00599 int flags, 00600 int numpts 00601 ); 00602 /* bell_utils.c */ 00603 REAL dualabell(REAL (*origbell) (int,int), 00604 int laplength, 00605 int t 00606 ); 00607 void bell_1size_init(REAL *bellout, 00608 REAL (*whichbell) (int,int), 00609 int lapleft, 00610 int center, 00611 int lapright, 00612 int dual_flag 00613 ); 00614 void fold_e_e_1s(REAL *coef, 00615 REAL *fcn, 00616 int numpts, 00617 REAL *left, 00618 int n_left, 00619 REAL *right, 00620 int n_right, 00621 REAL *bell, 00622 int dir 00623 ); 00624 void fold_e_o_1s(REAL *coef, 00625 REAL *fcn, 00626 int numpts, 00627 REAL *left, 00628 int n_left, 00629 REAL *right, 00630 int n_right, 00631 REAL *bell, 00632 int dir 00633 ); 00634 /* Pmn_construct.c */ 00635 REAL Pmncos(int order, 00636 int index, 00637 REAL phi 00638 ); 00639 void Pmncos_resave_init(Pmncos_Recurrence_Save *pmn_save, 00640 REAL *node, 00641 int numpts 00642 ); 00643 void next_rtsinPmncos(REAL *outfcn, 00644 Pmncos_Recurrence_Save *pmn_save, 00645 int halfpts, 00646 int order, 00647 int index 00648 ); 00649 void Pmncos_resave_destroy(Pmncos_Recurrence_Save *pmn_save 00650 ); 00651 /* direct1_tofile.c */ 00652 void direct1_tofile(int numpts, 00653 int band_limit, 00654 REAL *node, 00655 REAL *weight, 00656 FILE *fp 00657 ); 00658 void init_direct1(Pm_Direct_d **out, 00659 int halfpts, 00660 int band_limit, 00661 REAL *node 00662 ); 00663 void dump_direct1(int numpts, 00664 int band_limit, 00665 REAL *node, 00666 REAL *weight, 00667 Pm_Direct_d *pmn_matrix, 00668 FILE *fp 00669 ); 00670 /* fast1_tofile.c */ 00671 REAL fast1_tofile(int numpts, 00672 int band_limit, 00673 REAL *node, 00674 REAL *weight, 00675 REAL epsilon, 00676 FILE *fp 00677 ); 00678 void init_fast1(Pm_1D **out, 00679 Fast1_Save *saves_fordump, 00680 int halfpts, 00681 int band_limit, 00682 REAL *node, 00683 int *numlevels, 00684 REAL epsilon, 00685 REAL (*bell_choice) (int,int) 00686 ); 00687 void dump_fast1(int numpts, 00688 int band_limit, 00689 int num_levels, 00690 REAL *node, 00691 REAL *weight, 00692 Fast1_Save *saves_fordump, 00693 Pm_1D *pmn_matrix, 00694 FILE *fp 00695 ); 00696 /* direct1_transform.c */ 00697 void Pm_direct1_analyse(REAL *outcoef, 00698 Pm_Direct_d *inmat, 00699 REAL *infcn, 00700 Pm_1D_Workspace *pmnwork 00701 ); 00702 void Pm_direct1_synthesize(REAL *outfcn, 00703 Pm_Direct_d *inmat, 00704 REAL *incoef, 00705 Pm_1D_Workspace *pmnwork 00706 ); 00707 /* matbells.c */ 00708 REAL bellmat1(int laplength, 00709 int t 00710 ); 00711 REAL bellmat2(int laplength, 00712 int t 00713 ); 00714 REAL bellmat3(int laplength, 00715 int t 00716 ); 00717 REAL bellmat4(int laplength, 00718 int t 00719 ); 00720 REAL bellmat5(int laplength, 00721 int t 00722 ); 00723 REAL bellmat6(int laplength, 00724 int t 00725 ); 00726 REAL bellmat7(int laplength, 00727 int t 00728 ); 00729 REAL bellmat8(int laplength, 00730 int t 00731 ); 00732 REAL bellmat9(int laplength, 00733 int t 00734 ); 00735 REAL bellmat10(int laplength, 00736 int t 00737 ); 00738 REAL bellmat11(int laplength, 00739 int t 00740 ); 00741 REAL bellmat12(int laplength, 00742 int t 00743 ); 00744 REAL bellmat13(int laplength, 00745 int t 00746 ); 00747 REAL bellmat14(int laplength, 00748 int t 00749 ); 00750 REAL bellmat15(int laplength, 00751 int t 00752 ); 00753 REAL bellmat16(int laplength, 00754 int t 00755 ); 00756 REAL bellmat17(int laplength, 00757 int t 00758 ); 00759 REAL bellmat18(int laplength, 00760 int t 00761 ); 00762 REAL bellmat19(int laplength, 00763 int t 00764 ); 00765 REAL bellmat20(int laplength, 00766 int t 00767 ); 00768 /* fast1_transform.c */ 00769 void Pm_1d_analyse(REAL *outcoef, 00770 Pm_1D *inmat, 00771 REAL *infcn, 00772 Pm_1D_Workspace *pmnwork 00773 ); 00774 void Pm_1d_synthesize(REAL *outfcn, 00775 Pm_1D *inmat, 00776 REAL *incoef, 00777 Pm_1D_Workspace *pmnwork 00778 ); 00779 /* mk_gnode_gweight.c */ 00780 void mk_gnode_gweight(REAL *gnode, 00781 REAL *gweight, 00782 REAL epsilon, 00783 int numpts 00784 ); 00785 void mk_cosi_gnode(REAL *gnode, 00786 REAL epsilon, 00787 int numpts 00788 ); 00789 void cosi_gnode_to_gweight(REAL *gweight, 00790 REAL *gnode, 00791 int numpts 00792 ); 00793 /* second.c */ 00794 double second(); 00795 /* getoption.c */ 00796 char* getoption(const char* flag, 00797 int argc, 00798 char **argv 00799 ); 00800 /* pointwise_ops.c */ 00801 void pointwise_multiply(REAL *out, 00802 REAL *in_1, 00803 REAL *in_2, 00804 int numpts 00805 ); 00806 void reflect_evenodd(REAL *even, 00807 REAL *odd, 00808 REAL *whole, 00809 int numpts, 00810 int dir 00811 ); 00812 void remove_rootsin(REAL *out, 00813 REAL *in, 00814 REAL *node, 00815 int numpts 00816 ); 00817 /* dyadic_trig_gsearch.c */ 00818 void dyadic_g_ilist_init(Local_Trig_Interval *ilist[2], 00819 int *ints_used, 00820 int *coefs_used, 00821 REAL **bell_handle, 00822 int *bell_length, 00823 int **bell_offsets, 00824 int halfpts, 00825 int num_levels, 00826 REAL (*bell_choice) (int,int), 00827 int flags 00828 ); 00829 void ltrigint_init(Local_Trig_Interval *out, 00830 int numpts, 00831 int left_extra, 00832 int right_extra, 00833 int fcn_offset, 00834 int coef_offset, 00835 REAL (*bell_choice)(int,int), 00836 int which_transform, 00837 int fftw_flags 00838 ); 00839 void gsearch_to_ilist(Local_Trig_Interval *ilist_out, 00840 int *intervals_kept, 00841 int max_intervals, 00842 Local_Trig_Interval *ilist_in, 00843 Dyadic_Gsearch_Save *dy_gs_save, 00844 int halfpts 00845 ); 00846 /* trig_int_ops.c */ 00847 void evaluate_intlist(REAL *outfcn, 00848 REAL *incoef, 00849 Local_Trig_Interval *interval_list, 00850 int num_intervals 00851 ); 00852 void expand_d_intlist(REAL *outcoef, 00853 REAL *infcn, 00854 Local_Trig_Interval *interval_list, 00855 int num_intervals 00856 ); 00857 void expand_intlist(REAL *outcoef, 00858 REAL *infcn, 00859 Local_Trig_Interval *interval_list, 00860 int num_intervals 00861 ); 00862 /* count_thresh.c */ 00863 int count_thresh(REAL *lambda, 00864 int howmany, 00865 REAL thresh 00866 ); 00867 /* init_Pm_1d_workspace */ 00868 void init_Pm_1d_workspace(Pm_1D_Workspace *out, 00869 int numpts, 00870 int band_limit, 00871 REAL *node, 00872 REAL *weight 00873 ); 00874 00875 /* */ 00876 void ftgaqd(int *nlat, 00877 REAL *theta, 00878 REAL *wts, 00879 REAL *work, 00880 int *lwork, 00881 int *ierror 00882 ); 00883 void gnode_to_Pmninit(REAL ***sofar, 00884 REAL **ex, 00885 REAL **why, 00886 int **size, 00887 REAL *gnode, 00888 int hemipts 00889 ); 00890 00891 /*************************************************************************/ 00892 /******* END function prototypes *****************************************/ 00893 /*************************************************************************/ 00894 00895 #endif /* LIBFTSH_PRESENT */