JWS C Library
C language utility library
|
00001 /* 00002 * This work is licensed under a Creative Commons 00003 * Attribution-Noncommercial-Share Alike 3.0 United States License. 00004 * 00005 * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ 00006 * 00007 * You are free: 00008 * 00009 * to Share - to copy, distribute, display, and perform the work 00010 * to Remix - to make derivative works 00011 * 00012 * Under the following conditions: 00013 * 00014 * Attribution. You must attribute the work in the manner specified by the 00015 * author or licensor (but not in any way that suggests that they endorse you 00016 * or your use of the work). 00017 * 00018 * Noncommercial. You may not use this work for commercial purposes. 00019 * 00020 * Share Alike. If you alter, transform, or build upon this work, you may 00021 * distribute the resulting work only under the same or similar license to 00022 * this one. 00023 * 00024 * For any reuse or distribution, you must make clear to others the license 00025 * terms of this work. The best way to do this is by including this header. 00026 * 00027 * Any of the above conditions can be waived if you get permission from the 00028 * copyright holder. 00029 * 00030 * Apart from the remix rights granted under this license, nothing in this 00031 * license impairs or restricts the author's moral rights. 00032 */ 00033 00034 00050 #include <jwsc/config.h> 00051 00052 #include <stdlib.h> 00053 #include <inttypes.h> 00054 #include <assert.h> 00055 #include <math.h> 00056 #ifdef JWSC_HAVE_FFTW3_H 00057 #include <fftw3.h> 00058 #endif 00059 00060 #include "jwsc/matblock/matblock.h" 00061 #include "jwsc/matblock/matblock_math.h" 00062 #include "jwsc/matblock/matblock_fft.h" 00063 00064 00087 #ifdef JWSC_HAVE_FFTW3F 00088 void real_to_complex_matblock_dft_f 00089 ( 00090 Matblock_cf** m_out, 00091 const Matblock_f* m_in 00092 ) 00093 { 00094 Matblock_f* s = NULL; 00095 00096 real_to_complex_matblock_dft_scratch_f(m_out, m_in, &s); 00097 00098 free_matblock_f(s); 00099 } 00100 #endif 00101 00117 #ifdef JWSC_HAVE_FFTW3 00118 void real_to_complex_matblock_dft_d 00119 ( 00120 Matblock_cd** m_out, 00121 const Matblock_d* m_in 00122 ) 00123 { 00124 Matblock_d* s = NULL; 00125 00126 real_to_complex_matblock_dft_scratch_d(m_out, m_in, &s); 00127 00128 free_matblock_d(s); 00129 } 00130 #endif 00131 00161 #ifdef JWSC_HAVE_FFTW3F 00162 void real_to_complex_matblock_dft_scratch_f 00163 ( 00164 Matblock_cf** m_out, 00165 const Matblock_f* m_in, 00166 Matblock_f** s 00167 ) 00168 { 00169 uint32_t num_mats, num_rows, num_cols; 00170 fftwf_plan plan; 00171 00172 num_mats = m_in->num_mats; 00173 num_rows = m_in->num_rows; 00174 num_cols = m_in->num_cols; 00175 00176 create_matblock_cf(m_out, num_mats, num_rows, (num_cols/2)+1); 00177 00178 /* For fftw planning, input array does not need to be initialized, hence we 00179 * allow fftw to destroy the input to (possibly) get better efficiency. */ 00180 create_matblock_f(s, num_mats, num_rows, num_cols); 00181 00182 assert((plan = fftwf_plan_dft_r2c_3d(num_mats, num_rows, num_cols, 00183 **((*s)->elts), (fftwf_complex*)**((*m_out)->elts), 00184 FFTW_MEASURE | FFTW_DESTROY_INPUT)) != NULL); 00185 00186 /* Copy the input, now that planning is over, and execute. */ 00187 copy_matblock_f(s, m_in); 00188 fftwf_execute(plan); 00189 00190 fftwf_destroy_plan(plan); 00191 } 00192 #endif 00193 00210 #ifdef JWSC_HAVE_FFTW3 00211 void real_to_complex_matblock_dft_scratch_d 00212 ( 00213 Matblock_cd** m_out, 00214 const Matblock_d* m_in, 00215 Matblock_d** s 00216 ) 00217 { 00218 uint32_t num_mats, num_rows, num_cols; 00219 fftw_plan plan; 00220 00221 num_mats = m_in->num_mats; 00222 num_rows = m_in->num_rows; 00223 num_cols = m_in->num_cols; 00224 00225 create_matblock_cd(m_out, num_mats, num_rows, (num_cols/2)+1); 00226 00227 /* For fftw planning, input array does not need to be initialized, hence we 00228 * allow fftw to destroy the input to (possibly) get better efficiency. */ 00229 create_matblock_d(s, num_mats, num_rows, num_cols); 00230 00231 assert((plan = fftw_plan_dft_r2c_3d(num_mats, num_rows, num_cols, 00232 **((*s)->elts), (fftw_complex*)**((*m_out)->elts), 00233 FFTW_MEASURE | FFTW_DESTROY_INPUT)) != NULL); 00234 00235 /* Copy the input, now that planning is over, and execute. */ 00236 copy_matblock_d(s, m_in); 00237 fftw_execute(plan); 00238 00239 fftw_destroy_plan(plan); 00240 } 00241 #endif 00242 00282 #ifdef JWSC_HAVE_FFTW3F 00283 void complex_to_real_matblock_dft_f 00284 ( 00285 Matblock_f** m_out, 00286 const Matblock_cf* m_in, 00287 uint8_t ncols_even 00288 ) 00289 { 00290 Matblock_cf* s = NULL; 00291 00292 complex_to_real_matblock_dft_scratch_f(m_out, m_in, ncols_even, &s); 00293 00294 free_matblock_cf(s); 00295 } 00296 #endif 00297 00325 #ifdef JWSC_HAVE_FFTW3 00326 void complex_to_real_matblock_dft_d 00327 ( 00328 Matblock_d** m_out, 00329 const Matblock_cd* m_in, 00330 uint8_t ncols_even 00331 ) 00332 { 00333 Matblock_cd* s = NULL;; 00334 00335 complex_to_real_matblock_dft_scratch_d(m_out, m_in, ncols_even, &s); 00336 00337 free_matblock_cd(s); 00338 } 00339 #endif 00340 00382 #ifdef JWSC_HAVE_FFTW3F 00383 void complex_to_real_matblock_dft_scratch_f 00384 ( 00385 Matblock_f** m_out, 00386 const Matblock_cf* m_in, 00387 uint8_t ncols_even, 00388 Matblock_cf** s 00389 ) 00390 { 00391 uint32_t num_mats, num_rows, num_cols; 00392 fftwf_plan plan; 00393 00394 num_mats = m_in->num_mats; 00395 num_rows = m_in->num_rows; 00396 num_cols = (ncols_even) ? (m_in->num_cols-1)*2 : (m_in->num_cols-1)*2 + 1; 00397 00398 create_matblock_f(m_out, num_mats, num_rows, num_cols); 00399 00400 /* For fftw planning, input array does not need to be initialized, hence we 00401 * allow fftw to destroy the input to (possibly) get better efficiency. */ 00402 create_matblock_cf(s, m_in->num_mats, m_in->num_rows, m_in->num_cols); 00403 00404 assert((plan = fftwf_plan_dft_c2r_3d(num_mats, num_rows, num_cols, 00405 (fftwf_complex*)**((*s)->elts), **((*m_out)->elts), 00406 FFTW_MEASURE | FFTW_DESTROY_INPUT)) != NULL); 00407 00408 /* Copy the input, now that planning is over, and execute. */ 00409 copy_matblock_cf(s, m_in); 00410 fftwf_execute(plan); 00411 00412 fftwf_destroy_plan(plan); 00413 } 00414 #endif 00415 00444 #ifdef JWSC_HAVE_FFTW3 00445 void complex_to_real_matblock_dft_scratch_d 00446 ( 00447 Matblock_d** m_out, 00448 const Matblock_cd* m_in, 00449 uint8_t ncols_even, 00450 Matblock_cd** s 00451 ) 00452 { 00453 uint32_t num_mats, num_rows, num_cols; 00454 fftw_plan plan; 00455 00456 num_mats = m_in->num_mats; 00457 num_rows = m_in->num_rows; 00458 num_cols = (ncols_even) ? (m_in->num_cols-1)*2 : (m_in->num_cols-1)*2 + 1; 00459 00460 create_matblock_d(m_out, num_mats, num_rows, num_cols); 00461 00462 /* For fftw planning, input array does not need to be initialized, hence we 00463 * allow fftw to destroy the input to (possibly) get better efficiency. */ 00464 create_matblock_cd(s, m_in->num_mats, m_in->num_rows, m_in->num_cols); 00465 00466 assert((plan = fftw_plan_dft_c2r_3d(num_mats, num_rows, num_cols, 00467 (fftw_complex*)**((*s)->elts), **((*m_out)->elts), 00468 FFTW_MEASURE | FFTW_DESTROY_INPUT)) != NULL); 00469 00470 /* Copy the input, now that planning is over, and execute. */ 00471 copy_matblock_cd(s, m_in); 00472 fftw_execute(plan); 00473 00474 fftw_destroy_plan(plan); 00475 } 00476 #endif 00477 00499 void expand_symmetric_matblock_dft_f 00500 ( 00501 Matblock_cf** m_out, 00502 const Matblock_cf* m_in, 00503 uint8_t ncols_even 00504 ) 00505 { 00506 uint32_t num_mats, num_rows, num_cols; 00507 uint32_t mat, row, col; 00508 Matblock_cf* m; 00509 00510 num_mats = m_in->num_mats; 00511 num_rows = m_in->num_rows; 00512 num_cols = m_in->num_cols; 00513 00514 m = (*m_out == m_in) ? NULL : *m_out; 00515 if (ncols_even) 00516 { 00517 create_matblock_cf(&m, num_mats, num_rows, (m_in->num_cols-1)*2); 00518 } 00519 else 00520 { 00521 create_matblock_cf(&m, num_mats, num_rows, (m_in->num_cols-1)*2 + 1); 00522 } 00523 00524 assert(copy_matblock_block_into_matblock_cf(m, 0, 0, 0, m_in, 0, 0, 0, 00525 m_in->num_mats, m_in->num_rows, m_in->num_cols) == NULL); 00526 00527 for (mat = 0; mat < num_mats; mat++) 00528 { 00529 for (row = 0; row < num_rows; row++) 00530 { 00531 for (col = m->num_cols-1; col >= m_in->num_cols; col--) 00532 { 00533 m->elts[mat][row][col] = 00534 m_in->elts[mat][row][m->num_cols-col-1]; 00535 } 00536 } 00537 } 00538 00539 if (*m_out == m_in) 00540 { 00541 copy_matblock_cf(m_out, m); 00542 free_matblock_cf(m); 00543 } 00544 else 00545 { 00546 *m_out = m; 00547 } 00548 } 00549 00559 void expand_symmetric_matblock_dft_d 00560 ( 00561 Matblock_cd** m_out, 00562 const Matblock_cd* m_in, 00563 uint8_t ncols_even 00564 ) 00565 { 00566 uint32_t num_mats, num_rows, num_cols; 00567 uint32_t mat, row, col; 00568 Matblock_cd* m; 00569 00570 num_mats = m_in->num_mats; 00571 num_rows = m_in->num_rows; 00572 num_cols = m_in->num_cols; 00573 00574 m = (*m_out == m_in) ? NULL : *m_out; 00575 if (ncols_even) 00576 { 00577 create_matblock_cd(&m, num_mats, num_rows, (m_in->num_cols-1)*2); 00578 } 00579 else 00580 { 00581 create_matblock_cd(&m, num_mats, num_rows, (m_in->num_cols-1)*2 + 1); 00582 } 00583 00584 assert(copy_matblock_block_into_matblock_cd(m, 0, 0, 0, m_in, 0, 0, 0, 00585 m_in->num_mats, m_in->num_rows, m_in->num_cols) == NULL); 00586 00587 for (mat = 0; mat < num_mats; mat++) 00588 { 00589 for (row = 0; row < num_rows; row++) 00590 { 00591 for (col = m->num_cols-1; col >= m_in->num_cols; col--) 00592 { 00593 m->elts[mat][row][col] = 00594 m_in->elts[mat][row][m->num_cols-col-1]; 00595 } 00596 } 00597 } 00598 00599 if (*m_out == m_in) 00600 { 00601 copy_matblock_cd(m_out, m); 00602 free_matblock_cd(m); 00603 } 00604 else 00605 { 00606 *m_out = m; 00607 } 00608 } 00609 00629 void shrink_symmetric_matblock_dft_f 00630 ( 00631 Matblock_cf** m_out, 00632 const Matblock_cf* m_in 00633 ) 00634 { 00635 Matblock_cf* m; 00636 00637 m = (*m_out == m_in) ? NULL : *m_out; 00638 create_matblock_cf(&m, m_in->num_mats, m_in->num_rows, 00639 (m_in->num_cols/2)+1); 00640 00641 assert(copy_matblock_block_into_matblock_cf(m, 0, 0, 0, m_in, 0, 0, 0, 00642 m->num_mats, m->num_rows, m->num_cols) == NULL); 00643 00644 if (*m_out == m_in) 00645 { 00646 copy_matblock_cf(m_out, m); 00647 free_matblock_cf(m); 00648 } 00649 else 00650 { 00651 *m_out = m; 00652 } 00653 } 00654 00662 void shrink_symmetric_matblock_dft_d 00663 ( 00664 Matblock_cd** m_out, 00665 const Matblock_cd* m_in 00666 ) 00667 { 00668 Matblock_cd* m; 00669 00670 m = (*m_out == m_in) ? NULL : *m_out; 00671 create_matblock_cd(&m, m_in->num_mats, m_in->num_rows, 00672 (m_in->num_cols/2)+1); 00673 00674 assert(copy_matblock_block_into_matblock_cd(m, 0, 0, 0, m_in, 0, 0, 0, 00675 m->num_mats, m->num_rows, m->num_cols) == NULL); 00676 00677 if (*m_out == m_in) 00678 { 00679 copy_matblock_cd(m_out, m); 00680 free_matblock_cd(m); 00681 } 00682 else 00683 { 00684 *m_out = m; 00685 } 00686 } 00687 00711 void scale_matblock_dft_f(Matblock_f** m_out, const Matblock_f* m_in) 00712 { 00713 float scale; 00714 00715 scale = 1.0f / (float)(m_in->num_mats*m_in->num_rows*m_in->num_cols); 00716 multiply_matblock_by_scalar_f(m_out, m_in, scale); 00717 } 00718 00730 void scale_matblock_dft_d(Matblock_d** m_out, const Matblock_d* m_in) 00731 { 00732 float scale; 00733 00734 scale = 1.0 / (double)(m_in->num_mats*m_in->num_rows*m_in->num_cols); 00735 multiply_matblock_by_scalar_d(m_out, m_in, scale); 00736 } 00737 00759 void shift_matblock_f 00760 ( 00761 Matblock_f** m_out, 00762 const Matblock_f* m_in 00763 ) 00764 { 00765 uint32_t num_mats, num_rows, num_cols; 00766 uint32_t mat, row, col; 00767 uint32_t half_mats, half_rows, half_cols; 00768 00769 Matblock_f* m = NULL; 00770 00771 num_mats = m_in->num_mats; 00772 num_rows = m_in->num_rows; 00773 num_cols = m_in->num_cols; 00774 half_mats = num_mats / 2; 00775 half_rows = num_rows / 2; 00776 half_cols = num_cols / 2; 00777 00778 m = (*m_out == m_in) ? NULL : *m_out; 00779 create_matblock_f(&m, num_mats, num_rows, num_cols); 00780 00781 for (mat = 0; mat < num_mats; mat++) 00782 { 00783 if (mat < half_mats + (num_mats % 2)) 00784 { 00785 for (row = 0; row < num_rows; row++) 00786 { 00787 if (row < half_rows + (num_rows % 2)) 00788 { 00789 for (col = 0; col < num_cols; col++) 00790 { 00791 if (col < half_cols + (num_cols % 2)) 00792 { 00793 m->elts[ mat ][ row ][ col ] = m_in->elts 00794 [ mat + half_mats ] 00795 [ row + half_rows ] 00796 [ col + half_cols ]; 00797 } 00798 else 00799 { 00800 m->elts[ mat ][ row ][ col ] = m_in->elts 00801 [ mat + half_mats ] 00802 [ row + half_rows ] 00803 [ col - half_cols - (num_cols % 2) ]; 00804 } 00805 } 00806 } 00807 else 00808 { 00809 for (col = 0; col < num_cols; col++) 00810 { 00811 if (col < half_cols + (num_cols % 2)) 00812 { 00813 m->elts[ mat ][ row ][ col ] = m_in->elts 00814 [ mat + half_mats ] 00815 [ row - half_rows - (num_rows % 2) ] 00816 [ col + half_cols ]; 00817 } 00818 else 00819 { 00820 m->elts[ mat ][ row ][ col ] = m_in->elts 00821 [ mat + half_mats ] 00822 [ row - half_rows - (num_rows % 2) ] 00823 [ col - half_cols - (num_cols % 2) ]; 00824 } 00825 } 00826 } 00827 } 00828 } 00829 else 00830 { 00831 for (row = 0; row < num_rows; row++) 00832 { 00833 if (row < half_rows + (num_rows % 2)) 00834 { 00835 for (col = 0; col < num_cols; col++) 00836 { 00837 if (col < half_cols + (num_cols % 2)) 00838 { 00839 m->elts[ mat ][ row ][ col ] = m_in->elts 00840 [ mat - half_mats - (num_mats % 2) ] 00841 [ row + half_rows ] 00842 [ col + half_cols ]; 00843 } 00844 else 00845 { 00846 m->elts[ mat ][ row ][ col ] = m_in->elts 00847 [ mat - half_mats - (num_mats % 2) ] 00848 [ row + half_rows ] 00849 [ col - half_cols - (num_cols % 2) ]; 00850 } 00851 } 00852 } 00853 else 00854 { 00855 for (col = 0; col < num_cols; col++) 00856 { 00857 if (col < half_cols + (num_cols % 2)) 00858 { 00859 m->elts[ mat ][ row ][ col ] = m_in->elts 00860 [ mat - half_mats - (num_mats % 2) ] 00861 [ row - half_rows - (num_rows % 2) ] 00862 [ col + half_cols ]; 00863 } 00864 else 00865 { 00866 m->elts[ mat ][ row ][ col ] = m_in->elts 00867 [ mat - half_mats - (num_mats % 2) ] 00868 [ row - half_rows - (num_rows % 2) ] 00869 [ col - half_cols - (num_cols % 2) ]; 00870 } 00871 } 00872 } 00873 } 00874 } 00875 } 00876 00877 if (*m_out == m_in) 00878 { 00879 copy_matblock_f(m_out, m); 00880 free_matblock_f(m); 00881 } 00882 else 00883 { 00884 *m_out = m; 00885 } 00886 } 00887 00897 void shift_matblock_d 00898 ( 00899 Matblock_d** m_out, 00900 const Matblock_d* m_in 00901 ) 00902 { 00903 uint32_t num_mats, num_rows, num_cols; 00904 uint32_t mat, row, col; 00905 uint32_t half_mats, half_rows, half_cols; 00906 00907 Matblock_d* m = NULL; 00908 00909 num_mats = m_in->num_mats; 00910 num_rows = m_in->num_rows; 00911 num_cols = m_in->num_cols; 00912 half_mats = num_mats / 2; 00913 half_rows = num_rows / 2; 00914 half_cols = num_cols / 2; 00915 00916 m = (*m_out == m_in) ? NULL : *m_out; 00917 create_matblock_d(&m, num_mats, num_rows, num_cols); 00918 00919 for (mat = 0; mat < num_mats; mat++) 00920 { 00921 if (mat < half_mats + (num_mats % 2)) 00922 { 00923 for (row = 0; row < num_rows; row++) 00924 { 00925 if (row < half_rows + (num_rows % 2)) 00926 { 00927 for (col = 0; col < num_cols; col++) 00928 { 00929 if (col < half_cols + (num_cols % 2)) 00930 { 00931 m->elts[ mat ][ row ][ col ] = m_in->elts 00932 [ mat + half_mats ] 00933 [ row + half_rows ] 00934 [ col + half_cols ]; 00935 } 00936 else 00937 { 00938 m->elts[ mat ][ row ][ col ] = m_in->elts 00939 [ mat + half_mats ] 00940 [ row + half_rows ] 00941 [ col - half_cols - (num_cols % 2) ]; 00942 } 00943 } 00944 } 00945 else 00946 { 00947 for (col = 0; col < num_cols; col++) 00948 { 00949 if (col < half_cols + (num_cols % 2)) 00950 { 00951 m->elts[ mat ][ row ][ col ] = m_in->elts 00952 [ mat + half_mats ] 00953 [ row - half_rows - (num_rows % 2) ] 00954 [ col + half_cols ]; 00955 } 00956 else 00957 { 00958 m->elts[ mat ][ row ][ col ] = m_in->elts 00959 [ mat + half_mats ] 00960 [ row - half_rows - (num_rows % 2) ] 00961 [ col - half_cols - (num_cols % 2) ]; 00962 } 00963 } 00964 } 00965 } 00966 } 00967 else 00968 { 00969 for (row = 0; row < num_rows; row++) 00970 { 00971 if (row < half_rows + (num_rows % 2)) 00972 { 00973 for (col = 0; col < num_cols; col++) 00974 { 00975 if (col < half_cols + (num_cols % 2)) 00976 { 00977 m->elts[ mat ][ row ][ col ] = m_in->elts 00978 [ mat - half_mats - (num_mats % 2) ] 00979 [ row + half_rows ] 00980 [ col + half_cols ]; 00981 } 00982 else 00983 { 00984 m->elts[ mat ][ row ][ col ] = m_in->elts 00985 [ mat - half_mats - (num_mats % 2) ] 00986 [ row + half_rows ] 00987 [ col - half_cols - (num_cols % 2) ]; 00988 } 00989 } 00990 } 00991 else 00992 { 00993 for (col = 0; col < num_cols; col++) 00994 { 00995 if (col < half_cols + (num_cols % 2)) 00996 { 00997 m->elts[ mat ][ row ][ col ] = m_in->elts 00998 [ mat - half_mats - (num_mats % 2) ] 00999 [ row - half_rows - (num_rows % 2) ] 01000 [ col + half_cols ]; 01001 } 01002 else 01003 { 01004 m->elts[ mat ][ row ][ col ] = m_in->elts 01005 [ mat - half_mats - (num_mats % 2) ] 01006 [ row - half_rows - (num_rows % 2) ] 01007 [ col - half_cols - (num_cols % 2) ]; 01008 } 01009 } 01010 } 01011 } 01012 } 01013 } 01014 01015 if (*m_out == m_in) 01016 { 01017 copy_matblock_d(m_out, m); 01018 free_matblock_d(m); 01019 } 01020 else 01021 { 01022 *m_out = m; 01023 } 01024 } 01025 01035 void shift_matblock_cf 01036 ( 01037 Matblock_cf** m_out, 01038 const Matblock_cf* m_in 01039 ) 01040 { 01041 uint32_t num_mats, num_rows, num_cols; 01042 uint32_t mat, row, col; 01043 uint32_t half_mats, half_rows, half_cols; 01044 01045 Matblock_cf* m = NULL; 01046 01047 num_mats = m_in->num_mats; 01048 num_rows = m_in->num_rows; 01049 num_cols = m_in->num_cols; 01050 half_mats = num_mats / 2; 01051 half_rows = num_rows / 2; 01052 half_cols = num_cols / 2; 01053 01054 m = (*m_out == m_in) ? NULL : *m_out; 01055 create_matblock_cf(&m, num_mats, num_rows, num_cols); 01056 01057 for (mat = 0; mat < num_mats; mat++) 01058 { 01059 if (mat < half_mats + (num_mats % 2)) 01060 { 01061 for (row = 0; row < num_rows; row++) 01062 { 01063 if (row < half_rows + (num_rows % 2)) 01064 { 01065 for (col = 0; col < num_cols; col++) 01066 { 01067 if (col < half_cols + (num_cols % 2)) 01068 { 01069 m->elts[ mat ][ row ][ col ] = m_in->elts 01070 [ mat + half_mats ] 01071 [ row + half_rows ] 01072 [ col + half_cols ]; 01073 } 01074 else 01075 { 01076 m->elts[ mat ][ row ][ col ] = m_in->elts 01077 [ mat + half_mats ] 01078 [ row + half_rows ] 01079 [ col - half_cols - (num_cols % 2) ]; 01080 } 01081 } 01082 } 01083 else 01084 { 01085 for (col = 0; col < num_cols; col++) 01086 { 01087 if (col < half_cols + (num_cols % 2)) 01088 { 01089 m->elts[ mat ][ row ][ col ] = m_in->elts 01090 [ mat + half_mats ] 01091 [ row - half_rows - (num_rows % 2) ] 01092 [ col + half_cols ]; 01093 } 01094 else 01095 { 01096 m->elts[ mat ][ row ][ col ] = m_in->elts 01097 [ mat + half_mats ] 01098 [ row - half_rows - (num_rows % 2) ] 01099 [ col - half_cols - (num_cols % 2) ]; 01100 } 01101 } 01102 } 01103 } 01104 } 01105 else 01106 { 01107 for (row = 0; row < num_rows; row++) 01108 { 01109 if (row < half_rows + (num_rows % 2)) 01110 { 01111 for (col = 0; col < num_cols; col++) 01112 { 01113 if (col < half_cols + (num_cols % 2)) 01114 { 01115 m->elts[ mat ][ row ][ col ] = m_in->elts 01116 [ mat - half_mats - (num_mats % 2) ] 01117 [ row + half_rows ] 01118 [ col + half_cols ]; 01119 } 01120 else 01121 { 01122 m->elts[ mat ][ row ][ col ] = m_in->elts 01123 [ mat - half_mats - (num_mats % 2) ] 01124 [ row + half_rows ] 01125 [ col - half_cols - (num_cols % 2) ]; 01126 } 01127 } 01128 } 01129 else 01130 { 01131 for (col = 0; col < num_cols; col++) 01132 { 01133 if (col < half_cols + (num_cols % 2)) 01134 { 01135 m->elts[ mat ][ row ][ col ] = m_in->elts 01136 [ mat - half_mats - (num_mats % 2) ] 01137 [ row - half_rows - (num_rows % 2) ] 01138 [ col + half_cols ]; 01139 } 01140 else 01141 { 01142 m->elts[ mat ][ row ][ col ] = m_in->elts 01143 [ mat - half_mats - (num_mats % 2) ] 01144 [ row - half_rows - (num_rows % 2) ] 01145 [ col - half_cols - (num_cols % 2) ]; 01146 } 01147 } 01148 } 01149 } 01150 } 01151 } 01152 01153 if (*m_out == m_in) 01154 { 01155 copy_matblock_cf(m_out, m); 01156 free_matblock_cf(m); 01157 } 01158 else 01159 { 01160 *m_out = m; 01161 } 01162 } 01163 01173 void shift_matblock_cd 01174 ( 01175 Matblock_cd** m_out, 01176 const Matblock_cd* m_in 01177 ) 01178 { 01179 uint32_t num_mats, num_rows, num_cols; 01180 uint32_t mat, row, col; 01181 uint32_t half_mats, half_rows, half_cols; 01182 01183 Matblock_cd* m = NULL; 01184 01185 num_mats = m_in->num_mats; 01186 num_rows = m_in->num_rows; 01187 num_cols = m_in->num_cols; 01188 half_mats = num_mats / 2; 01189 half_rows = num_rows / 2; 01190 half_cols = num_cols / 2; 01191 01192 m = (*m_out == m_in) ? NULL : *m_out; 01193 create_matblock_cd(&m, num_mats, num_rows, num_cols); 01194 01195 for (mat = 0; mat < num_mats; mat++) 01196 { 01197 if (mat < half_mats + (num_mats % 2)) 01198 { 01199 for (row = 0; row < num_rows; row++) 01200 { 01201 if (row < half_rows + (num_rows % 2)) 01202 { 01203 for (col = 0; col < num_cols; col++) 01204 { 01205 if (col < half_cols + (num_cols % 2)) 01206 { 01207 m->elts[ mat ][ row ][ col ] = m_in->elts 01208 [ mat + half_mats ] 01209 [ row + half_rows ] 01210 [ col + half_cols ]; 01211 } 01212 else 01213 { 01214 m->elts[ mat ][ row ][ col ] = m_in->elts 01215 [ mat + half_mats ] 01216 [ row + half_rows ] 01217 [ col - half_cols - (num_cols % 2) ]; 01218 } 01219 } 01220 } 01221 else 01222 { 01223 for (col = 0; col < num_cols; col++) 01224 { 01225 if (col < half_cols + (num_cols % 2)) 01226 { 01227 m->elts[ mat ][ row ][ col ] = m_in->elts 01228 [ mat + half_mats ] 01229 [ row - half_rows - (num_rows % 2) ] 01230 [ col + half_cols ]; 01231 } 01232 else 01233 { 01234 m->elts[ mat ][ row ][ col ] = m_in->elts 01235 [ mat + half_mats ] 01236 [ row - half_rows - (num_rows % 2) ] 01237 [ col - half_cols - (num_cols % 2) ]; 01238 } 01239 } 01240 } 01241 } 01242 } 01243 else 01244 { 01245 for (row = 0; row < num_rows; row++) 01246 { 01247 if (row < half_rows + (num_rows % 2)) 01248 { 01249 for (col = 0; col < num_cols; col++) 01250 { 01251 if (col < half_cols + (num_cols % 2)) 01252 { 01253 m->elts[ mat ][ row ][ col ] = m_in->elts 01254 [ mat - half_mats - (num_mats % 2) ] 01255 [ row + half_rows ] 01256 [ col + half_cols ]; 01257 } 01258 else 01259 { 01260 m->elts[ mat ][ row ][ col ] = m_in->elts 01261 [ mat - half_mats - (num_mats % 2) ] 01262 [ row + half_rows ] 01263 [ col - half_cols - (num_cols % 2) ]; 01264 } 01265 } 01266 } 01267 else 01268 { 01269 for (col = 0; col < num_cols; col++) 01270 { 01271 if (col < half_cols + (num_cols % 2)) 01272 { 01273 m->elts[ mat ][ row ][ col ] = m_in->elts 01274 [ mat - half_mats - (num_mats % 2) ] 01275 [ row - half_rows - (num_rows % 2) ] 01276 [ col + half_cols ]; 01277 } 01278 else 01279 { 01280 m->elts[ mat ][ row ][ col ] = m_in->elts 01281 [ mat - half_mats - (num_mats % 2) ] 01282 [ row - half_rows - (num_rows % 2) ] 01283 [ col - half_cols - (num_cols % 2) ]; 01284 } 01285 } 01286 } 01287 } 01288 } 01289 } 01290 01291 if (*m_out == m_in) 01292 { 01293 copy_matblock_cd(m_out, m); 01294 free_matblock_cd(m); 01295 } 01296 else 01297 { 01298 *m_out = m; 01299 } 01300 } 01301 01323 void unshift_matblock_f 01324 ( 01325 Matblock_f** m_out, 01326 const Matblock_f* m_in 01327 ) 01328 { 01329 uint32_t num_mats, num_rows, num_cols; 01330 uint32_t mat, row, col; 01331 uint32_t half_mats, half_rows, half_cols; 01332 01333 Matblock_f* m = NULL; 01334 01335 num_mats = m_in->num_mats; 01336 num_rows = m_in->num_rows; 01337 num_cols = m_in->num_cols; 01338 half_mats = num_mats / 2; 01339 half_rows = num_rows / 2; 01340 half_cols = num_cols / 2; 01341 01342 m = (*m_out == m_in) ? NULL : *m_out; 01343 create_matblock_f(&m, num_mats, num_rows, num_cols); 01344 01345 for (mat = 0; mat < num_mats; mat++) 01346 { 01347 if (mat < half_mats) 01348 { 01349 for (row = 0; row < num_rows; row++) 01350 { 01351 if (row < half_rows) 01352 { 01353 for (col = 0; col < num_cols; col++) 01354 { 01355 if (col < half_cols) 01356 { 01357 m->elts[ mat ][ row ][ col ] = m_in->elts 01358 [ mat + half_mats + (num_mats % 2) ] 01359 [ row + half_rows + (num_rows % 2) ] 01360 [ col + half_cols + (num_cols % 2) ]; 01361 } 01362 else 01363 { 01364 m->elts[ mat ][ row ][ col ] = m_in->elts 01365 [ mat + half_mats + (num_mats % 2) ] 01366 [ row + half_rows + (num_rows % 2) ] 01367 [ col - half_cols ]; 01368 } 01369 } 01370 } 01371 else 01372 { 01373 for (col = 0; col < num_cols; col++) 01374 { 01375 if (col < half_cols) 01376 { 01377 m->elts[ mat ][ row ][ col ] = m_in->elts 01378 [ mat + half_mats + (num_mats % 2) ] 01379 [ row - half_rows ] 01380 [ col + half_cols + (num_cols % 2) ]; 01381 } 01382 else 01383 { 01384 m->elts[ mat ][ row ][ col ] = m_in->elts 01385 [ mat + half_mats + (num_mats % 2) ] 01386 [ row - half_rows] 01387 [ col - half_cols]; 01388 } 01389 } 01390 } 01391 } 01392 } 01393 else 01394 { 01395 for (row = 0; row < num_rows; row++) 01396 { 01397 if (row < half_rows) 01398 { 01399 for (col = 0; col < num_cols; col++) 01400 { 01401 if (col < half_cols) 01402 { 01403 m->elts[ mat ][ row ][ col ] = m_in->elts 01404 [ mat - half_mats ] 01405 [ row + half_rows + (num_rows % 2) ] 01406 [ col + half_cols + (num_cols % 2) ]; 01407 } 01408 else 01409 { 01410 m->elts[ mat ][ row ][ col ] = m_in->elts 01411 [ mat - half_mats ] 01412 [ row + half_rows + (num_rows % 2) ] 01413 [ col - half_cols ]; 01414 } 01415 } 01416 } 01417 else 01418 { 01419 for (col = 0; col < num_cols; col++) 01420 { 01421 if (col < half_cols) 01422 { 01423 m->elts[ mat ][ row ][ col ] = m_in->elts 01424 [ mat - half_mats ] 01425 [ row - half_rows ] 01426 [ col + half_cols + (num_cols % 2) ]; 01427 } 01428 else 01429 { 01430 m->elts[ mat ][ row ][ col ] = m_in->elts 01431 [ mat - half_mats ] 01432 [ row - half_rows] 01433 [ col - half_cols]; 01434 } 01435 } 01436 } 01437 } 01438 } 01439 } 01440 01441 if (*m_out == m_in) 01442 { 01443 copy_matblock_f(m_out, m); 01444 free_matblock_f(m); 01445 } 01446 else 01447 { 01448 *m_out = m; 01449 } 01450 } 01451 01461 void unshift_matblock_d 01462 ( 01463 Matblock_d** m_out, 01464 const Matblock_d* m_in 01465 ) 01466 { 01467 uint32_t num_mats, num_rows, num_cols; 01468 uint32_t mat, row, col; 01469 uint32_t half_mats, half_rows, half_cols; 01470 01471 Matblock_d* m = NULL; 01472 01473 num_mats = m_in->num_mats; 01474 num_rows = m_in->num_rows; 01475 num_cols = m_in->num_cols; 01476 half_mats = num_mats / 2; 01477 half_rows = num_rows / 2; 01478 half_cols = num_cols / 2; 01479 01480 m = (*m_out == m_in) ? NULL : *m_out; 01481 create_matblock_d(&m, num_mats, num_rows, num_cols); 01482 01483 for (mat = 0; mat < num_mats; mat++) 01484 { 01485 if (mat < half_mats) 01486 { 01487 for (row = 0; row < num_rows; row++) 01488 { 01489 if (row < half_rows) 01490 { 01491 for (col = 0; col < num_cols; col++) 01492 { 01493 if (col < half_cols) 01494 { 01495 m->elts[ mat ][ row ][ col ] = m_in->elts 01496 [ mat + half_mats + (num_mats % 2) ] 01497 [ row + half_rows + (num_rows % 2) ] 01498 [ col + half_cols + (num_cols % 2) ]; 01499 } 01500 else 01501 { 01502 m->elts[ mat ][ row ][ col ] = m_in->elts 01503 [ mat + half_mats + (num_mats % 2) ] 01504 [ row + half_rows + (num_rows % 2) ] 01505 [ col - half_cols ]; 01506 } 01507 } 01508 } 01509 else 01510 { 01511 for (col = 0; col < num_cols; col++) 01512 { 01513 if (col < half_cols) 01514 { 01515 m->elts[ mat ][ row ][ col ] = m_in->elts 01516 [ mat + half_mats + (num_mats % 2) ] 01517 [ row - half_rows ] 01518 [ col + half_cols + (num_cols % 2) ]; 01519 } 01520 else 01521 { 01522 m->elts[ mat ][ row ][ col ] = m_in->elts 01523 [ mat + half_mats + (num_mats % 2) ] 01524 [ row - half_rows] 01525 [ col - half_cols]; 01526 } 01527 } 01528 } 01529 } 01530 } 01531 else 01532 { 01533 for (row = 0; row < num_rows; row++) 01534 { 01535 if (row < half_rows) 01536 { 01537 for (col = 0; col < num_cols; col++) 01538 { 01539 if (col < half_cols) 01540 { 01541 m->elts[ mat ][ row ][ col ] = m_in->elts 01542 [ mat - half_mats ] 01543 [ row + half_rows + (num_rows % 2) ] 01544 [ col + half_cols + (num_cols % 2) ]; 01545 } 01546 else 01547 { 01548 m->elts[ mat ][ row ][ col ] = m_in->elts 01549 [ mat - half_mats ] 01550 [ row + half_rows + (num_rows % 2) ] 01551 [ col - half_cols ]; 01552 } 01553 } 01554 } 01555 else 01556 { 01557 for (col = 0; col < num_cols; col++) 01558 { 01559 if (col < half_cols) 01560 { 01561 m->elts[ mat ][ row ][ col ] = m_in->elts 01562 [ mat - half_mats ] 01563 [ row - half_rows ] 01564 [ col + half_cols + (num_cols % 2) ]; 01565 } 01566 else 01567 { 01568 m->elts[ mat ][ row ][ col ] = m_in->elts 01569 [ mat - half_mats ] 01570 [ row - half_rows] 01571 [ col - half_cols]; 01572 } 01573 } 01574 } 01575 } 01576 } 01577 } 01578 01579 if (*m_out == m_in) 01580 { 01581 copy_matblock_d(m_out, m); 01582 free_matblock_d(m); 01583 } 01584 else 01585 { 01586 *m_out = m; 01587 } 01588 } 01589 01599 void unshift_matblock_cf 01600 ( 01601 Matblock_cf** m_out, 01602 const Matblock_cf* m_in 01603 ) 01604 { 01605 uint32_t num_mats, num_rows, num_cols; 01606 uint32_t mat, row, col; 01607 uint32_t half_mats, half_rows, half_cols; 01608 01609 Matblock_cf* m = NULL; 01610 01611 num_mats = m_in->num_mats; 01612 num_rows = m_in->num_rows; 01613 num_cols = m_in->num_cols; 01614 half_mats = num_mats / 2; 01615 half_rows = num_rows / 2; 01616 half_cols = num_cols / 2; 01617 01618 m = (*m_out == m_in) ? NULL : *m_out; 01619 create_matblock_cf(&m, num_mats, num_rows, num_cols); 01620 01621 for (mat = 0; mat < num_mats; mat++) 01622 { 01623 if (mat < half_mats) 01624 { 01625 for (row = 0; row < num_rows; row++) 01626 { 01627 if (row < half_rows) 01628 { 01629 for (col = 0; col < num_cols; col++) 01630 { 01631 if (col < half_cols) 01632 { 01633 m->elts[ mat ][ row ][ col ] = m_in->elts 01634 [ mat + half_mats + (num_mats % 2) ] 01635 [ row + half_rows + (num_rows % 2) ] 01636 [ col + half_cols + (num_cols % 2) ]; 01637 } 01638 else 01639 { 01640 m->elts[ mat ][ row ][ col ] = m_in->elts 01641 [ mat + half_mats + (num_mats % 2) ] 01642 [ row + half_rows + (num_rows % 2) ] 01643 [ col - half_cols ]; 01644 } 01645 } 01646 } 01647 else 01648 { 01649 for (col = 0; col < num_cols; col++) 01650 { 01651 if (col < half_cols) 01652 { 01653 m->elts[ mat ][ row ][ col ] = m_in->elts 01654 [ mat + half_mats + (num_mats % 2) ] 01655 [ row - half_rows ] 01656 [ col + half_cols + (num_cols % 2) ]; 01657 } 01658 else 01659 { 01660 m->elts[ mat ][ row ][ col ] = m_in->elts 01661 [ mat + half_mats + (num_mats % 2) ] 01662 [ row - half_rows] 01663 [ col - half_cols]; 01664 } 01665 } 01666 } 01667 } 01668 } 01669 else 01670 { 01671 for (row = 0; row < num_rows; row++) 01672 { 01673 if (row < half_rows) 01674 { 01675 for (col = 0; col < num_cols; col++) 01676 { 01677 if (col < half_cols) 01678 { 01679 m->elts[ mat ][ row ][ col ] = m_in->elts 01680 [ mat - half_cols ] 01681 [ row + half_rows + (num_rows % 2) ] 01682 [ col + half_cols + (num_cols % 2) ]; 01683 } 01684 else 01685 { 01686 m->elts[ mat ][ row ][ col ] = m_in->elts 01687 [ mat - half_cols ] 01688 [ row + half_rows + (num_rows % 2) ] 01689 [ col - half_cols ]; 01690 } 01691 } 01692 } 01693 else 01694 { 01695 for (col = 0; col < num_cols; col++) 01696 { 01697 if (col < half_cols) 01698 { 01699 m->elts[ mat ][ row ][ col ] = m_in->elts 01700 [ mat - half_cols ] 01701 [ row - half_rows ] 01702 [ col + half_cols + (num_cols % 2) ]; 01703 } 01704 else 01705 { 01706 m->elts[ mat ][ row ][ col ] = m_in->elts 01707 [ mat - half_cols ] 01708 [ row - half_rows] 01709 [ col - half_cols]; 01710 } 01711 } 01712 } 01713 } 01714 } 01715 } 01716 01717 if (*m_out == m_in) 01718 { 01719 copy_matblock_cf(m_out, m); 01720 free_matblock_cf(m); 01721 } 01722 else 01723 { 01724 *m_out = m; 01725 } 01726 } 01727 01737 void unshift_matblock_cd 01738 ( 01739 Matblock_cd** m_out, 01740 const Matblock_cd* m_in 01741 ) 01742 { 01743 uint32_t num_mats, num_rows, num_cols; 01744 uint32_t mat, row, col; 01745 uint32_t half_mats, half_rows, half_cols; 01746 01747 Matblock_cd* m = NULL; 01748 01749 num_mats = m_in->num_mats; 01750 num_rows = m_in->num_rows; 01751 num_cols = m_in->num_cols; 01752 half_mats = num_mats / 2; 01753 half_rows = num_rows / 2; 01754 half_cols = num_cols / 2; 01755 01756 m = (*m_out == m_in) ? NULL : *m_out; 01757 create_matblock_cd(&m, num_mats, num_rows, num_cols); 01758 01759 for (mat = 0; mat < num_mats; mat++) 01760 { 01761 if (mat < half_mats) 01762 { 01763 for (row = 0; row < num_rows; row++) 01764 { 01765 if (row < half_rows) 01766 { 01767 for (col = 0; col < num_cols; col++) 01768 { 01769 if (col < half_cols) 01770 { 01771 m->elts[ mat ][ row ][ col ] = m_in->elts 01772 [ mat + half_mats + (num_mats % 2) ] 01773 [ row + half_rows + (num_rows % 2) ] 01774 [ col + half_cols + (num_cols % 2) ]; 01775 } 01776 else 01777 { 01778 m->elts[ mat ][ row ][ col ] = m_in->elts 01779 [ mat + half_mats + (num_mats % 2) ] 01780 [ row + half_rows + (num_rows % 2) ] 01781 [ col - half_cols ]; 01782 } 01783 } 01784 } 01785 else 01786 { 01787 for (col = 0; col < num_cols; col++) 01788 { 01789 if (col < half_cols) 01790 { 01791 m->elts[ mat ][ row ][ col ] = m_in->elts 01792 [ mat + half_mats + (num_mats % 2) ] 01793 [ row - half_rows ] 01794 [ col + half_cols + (num_cols % 2) ]; 01795 } 01796 else 01797 { 01798 m->elts[ mat ][ row ][ col ] = m_in->elts 01799 [ mat + half_mats + (num_mats % 2) ] 01800 [ row - half_rows] 01801 [ col - half_cols]; 01802 } 01803 } 01804 } 01805 } 01806 } 01807 else 01808 { 01809 for (row = 0; row < num_rows; row++) 01810 { 01811 if (row < half_rows) 01812 { 01813 for (col = 0; col < num_cols; col++) 01814 { 01815 if (col < half_cols) 01816 { 01817 m->elts[ mat ][ row ][ col ] = m_in->elts 01818 [ mat - half_cols ] 01819 [ row + half_rows + (num_rows % 2) ] 01820 [ col + half_cols + (num_cols % 2) ]; 01821 } 01822 else 01823 { 01824 m->elts[ mat ][ row ][ col ] = m_in->elts 01825 [ mat - half_cols ] 01826 [ row + half_rows + (num_rows % 2) ] 01827 [ col - half_cols ]; 01828 } 01829 } 01830 } 01831 else 01832 { 01833 for (col = 0; col < num_cols; col++) 01834 { 01835 if (col < half_cols) 01836 { 01837 m->elts[ mat ][ row ][ col ] = m_in->elts 01838 [ mat - half_cols ] 01839 [ row - half_rows ] 01840 [ col + half_cols + (num_cols % 2) ]; 01841 } 01842 else 01843 { 01844 m->elts[ mat ][ row ][ col ] = m_in->elts 01845 [ mat - half_cols ] 01846 [ row - half_rows] 01847 [ col - half_cols]; 01848 } 01849 } 01850 } 01851 } 01852 } 01853 } 01854 01855 if (*m_out == m_in) 01856 { 01857 copy_matblock_cd(m_out, m); 01858 free_matblock_cd(m); 01859 } 01860 else 01861 { 01862 *m_out = m; 01863 } 01864 } 01865