JWS C Library
C language utility library
matblock_fft.c
Go to the documentation of this file.
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