JWS C Library
C language utility library
matrix_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/matrix/matrix.h"
00061 #include "jwsc/matrix/matrix_math.h"
00062 
00063 
00086 #ifdef JWSC_HAVE_FFTW3F
00087 void real_to_complex_matrix_dft_f
00088 (
00089     Matrix_cf**     m_out,
00090     const Matrix_f* m_in
00091 )
00092 {
00093     uint32_t    num_rows, num_cols;
00094     Matrix_f*   m_in_copy;
00095     fftwf_plan  plan;
00096 
00097     num_rows = m_in->num_rows;
00098     num_cols = m_in->num_cols;
00099 
00100     create_matrix_cf(m_out, num_rows, (num_cols/2)+1);
00101 
00102     /* For fftw planning, input array does not need to be initialized, hence we
00103      * allow fftw to destroy the input to (possibly) get better efficiency. */
00104     m_in_copy = NULL;
00105     create_matrix_f(&m_in_copy, num_rows, num_cols);
00106 
00107     assert((plan = fftwf_plan_dft_r2c_2d(num_rows, num_cols,
00108                     *(m_in_copy->elts), (fftwf_complex*)*((*m_out)->elts), 
00109                     FFTW_MEASURE | FFTW_DESTROY_INPUT)) != NULL);
00110 
00111     /* Copy the input, now that planning is over, and execute. */
00112     copy_matrix_f(&m_in_copy, m_in);
00113     fftwf_execute(plan);
00114 
00115     fftwf_destroy_plan(plan);
00116     free_matrix_f(m_in_copy);
00117 }
00118 #endif
00119 
00135 #ifdef JWSC_HAVE_FFTW3
00136 void real_to_complex_matrix_dft_d
00137 (
00138     Matrix_cd**     m_out,
00139     const Matrix_d* m_in
00140 )
00141 {
00142     uint32_t    num_rows, num_cols;
00143     Matrix_d*   m_in_copy;
00144     fftw_plan   plan;
00145 
00146     num_rows = m_in->num_rows;
00147     num_cols = m_in->num_cols;
00148 
00149     create_matrix_cd(m_out, num_rows, (num_cols/2)+1);
00150 
00151     /* For fftw planning, input array does not need to be initialized, hence we
00152      * allow fftw to destroy the input to (possibly) get better efficiency. */
00153     m_in_copy = NULL;
00154     create_matrix_d(&m_in_copy, num_rows, num_cols);
00155 
00156     assert((plan = fftw_plan_dft_r2c_2d(num_rows, num_cols,
00157                     *(m_in_copy->elts), (fftw_complex*)*((*m_out)->elts), 
00158                     FFTW_MEASURE | FFTW_DESTROY_INPUT)) != NULL);
00159 
00160     /* Copy the input, now that planning is over, and execute. */
00161     copy_matrix_d(&m_in_copy, m_in);
00162     fftw_execute(plan);
00163 
00164     fftw_destroy_plan(plan);
00165     free_matrix_d(m_in_copy);
00166 }
00167 #endif
00168 
00208 #ifdef JWSC_HAVE_FFTW3F
00209 void complex_to_real_matrix_dft_f
00210 (
00211     Matrix_f**       m_out,
00212     const Matrix_cf* m_in,
00213     uint8_t          ncols_even
00214 )
00215 {
00216     uint32_t   num_rows, num_cols;
00217     Matrix_cf* m_in_copy;
00218     fftwf_plan plan;
00219 
00220     num_rows = m_in->num_rows;
00221     num_cols = (ncols_even) ? (m_in->num_cols-1)*2 : (m_in->num_cols-1)*2 + 1;
00222 
00223     create_matrix_f(m_out, num_rows, num_cols);
00224 
00225     /* For fftw planning, input array does not need to be initialized, hence we
00226      * allow fftw to destroy the input to (possibly) get better efficiency. */
00227     m_in_copy = NULL;
00228     create_matrix_cf(&m_in_copy, m_in->num_rows, m_in->num_cols);
00229 
00230     assert((plan = fftwf_plan_dft_c2r_2d(num_rows, num_cols,
00231                     (fftwf_complex*)*(m_in_copy->elts), *((*m_out)->elts), 
00232                     FFTW_MEASURE | FFTW_DESTROY_INPUT)) != NULL);
00233 
00234     /* Copy the input, now that planning is over, and execute. */
00235     copy_matrix_cf(&m_in_copy, m_in);
00236     fftwf_execute(plan);
00237 
00238     fftwf_destroy_plan(plan);
00239     free_matrix_cf(m_in_copy);
00240 }
00241 #endif
00242 
00270 #ifdef JWSC_HAVE_FFTW3
00271 void complex_to_real_matrix_dft_d
00272 (
00273     Matrix_d**       m_out,
00274     const Matrix_cd* m_in,
00275     uint8_t          ncols_even
00276 )
00277 {
00278     uint32_t   num_rows, num_cols;
00279     Matrix_cd* m_in_copy;
00280     fftw_plan  plan;
00281 
00282     num_rows = m_in->num_rows;
00283     num_cols = (ncols_even) ? (m_in->num_cols-1)*2 : (m_in->num_cols-1)*2 + 1;
00284 
00285     create_matrix_d(m_out, num_rows, num_cols);
00286 
00287     /* For fftw planning, input array does not need to be initialized, hence we
00288      * allow fftw to destroy the input to (possibly) get better efficiency. */
00289     m_in_copy = NULL;
00290     create_matrix_cd(&m_in_copy, m_in->num_rows, m_in->num_cols);
00291 
00292     assert((plan = fftw_plan_dft_c2r_2d(num_rows, num_cols,
00293                     (fftw_complex*)*(m_in_copy->elts), *((*m_out)->elts), 
00294                     FFTW_MEASURE | FFTW_DESTROY_INPUT)) != NULL);
00295 
00296     /* Copy the input, now that planning is over, and execute. */
00297     copy_matrix_cd(&m_in_copy, m_in);
00298     fftw_execute(plan);
00299 
00300     fftw_destroy_plan(plan);
00301     free_matrix_cd(m_in_copy);
00302 }
00303 #endif
00304 
00326 void expand_symmetric_matrix_dft_f
00327 (
00328     Matrix_cf**      m_out, 
00329     const Matrix_cf* m_in, 
00330     uint8_t          ncols_even
00331 )
00332 {
00333     uint32_t   num_rows, num_cols;
00334     uint32_t   row, col;
00335     Matrix_cf* m;
00336 
00337     num_rows = m_in->num_rows;
00338     num_cols = m_in->num_cols;
00339 
00340     m = (*m_out == m_in) ? NULL : *m_out;
00341     if (ncols_even)
00342     {
00343         create_matrix_cf(&m, num_rows, (m_in->num_cols-1)*2);
00344     }
00345     else
00346     {
00347         create_matrix_cf(&m, num_rows, (m_in->num_cols-1)*2 + 1);
00348     }
00349 
00350     assert(copy_matrix_block_into_matrix_cf(m, 0, 0, m_in, 0, 0, 
00351                 m_in->num_rows, m_in->num_cols) == NULL);
00352 
00353     for (row = 0; row < num_rows; row++)
00354     {
00355         for (col = m->num_cols-1; col >= m_in->num_cols; col--)
00356         {
00357             m->elts[row][col] = m_in->elts[row][m->num_cols-col-1];
00358         }
00359     }
00360 
00361     if (*m_out == m_in)
00362     {
00363         copy_matrix_cf(m_out, m);
00364         free_matrix_cf(m);
00365     }
00366     else
00367     {
00368         *m_out = m;
00369     }
00370 }
00371 
00381 void expand_symmetric_matrix_dft_d
00382 (
00383     Matrix_cd**      m_out, 
00384     const Matrix_cd* m_in, 
00385     uint8_t          ncols_even
00386 )
00387 {
00388     uint32_t   num_rows, num_cols;
00389     uint32_t   row, col;
00390     Matrix_cd* m;
00391 
00392     num_rows = m_in->num_rows;
00393     num_cols = m_in->num_cols;
00394 
00395     m = (*m_out == m_in) ? NULL : *m_out;
00396     if (ncols_even)
00397     {
00398         create_matrix_cd(&m, num_rows, (m_in->num_cols-1)*2);
00399     }
00400     else
00401     {
00402         create_matrix_cd(&m, num_rows, (m_in->num_cols-1)*2 + 1);
00403     }
00404 
00405     assert(copy_matrix_block_into_matrix_cd(m, 0, 0, m_in, 0, 0, 
00406                 m_in->num_rows, m_in->num_cols) == NULL);
00407 
00408     for (row = 0; row < num_rows; row++)
00409     {
00410         for (col = m->num_cols-1; col >= m_in->num_cols; col--)
00411         {
00412             m->elts[row][col] = m_in->elts[row][m->num_cols-col-1];
00413         }
00414     }
00415 
00416     if (*m_out == m_in)
00417     {
00418         copy_matrix_cd(m_out, m);
00419         free_matrix_cd(m);
00420     }
00421     else
00422     {
00423         *m_out = m;
00424     }
00425 }
00426 
00446 void shrink_symmetric_matrix_dft_f(Matrix_cf** m_out, const Matrix_cf* m_in)
00447 {
00448     Matrix_cf* m;
00449 
00450     m = (*m_out == m_in) ? NULL : *m_out;
00451     create_matrix_cf(&m, m_in->num_rows, (m_in->num_cols/2)+1);
00452 
00453     assert(copy_matrix_block_into_matrix_cf(m, 0, 0, m_in, 0, 0, 
00454                 m->num_rows, m->num_cols) == NULL);
00455 
00456     if (*m_out == m_in)
00457     {
00458         copy_matrix_cf(m_out, m);
00459         free_matrix_cf(m);
00460     }
00461     else
00462     {
00463         *m_out = m;
00464     }
00465 }
00466 
00474 void shrink_symmetric_matrix_dft_d(Matrix_cd** m_out, const Matrix_cd* m_in)
00475 {
00476     Matrix_cd* m;
00477 
00478     m = (*m_out == m_in) ? NULL : *m_out;
00479     create_matrix_cd(&m, m_in->num_rows, (m_in->num_cols/2)+1);
00480 
00481     assert(copy_matrix_block_into_matrix_cd(m, 0, 0, m_in, 0, 0, 
00482                 m->num_rows, m->num_cols) == NULL);
00483 
00484     if (*m_out == m_in)
00485     {
00486         copy_matrix_cd(m_out, m);
00487         free_matrix_cd(m);
00488     }
00489     else
00490     {
00491         *m_out = m;
00492     }
00493 }
00494 
00518 void scale_matrix_dft_f(Matrix_f** m_out, const Matrix_f* m_in)
00519 {
00520     float scale;
00521 
00522     scale = 1.0f / (float)(m_in->num_rows*m_in->num_cols);
00523     multiply_matrix_by_scalar_f(m_out, m_in, scale);
00524 }
00525 
00537 void scale_matrix_dft_d(Matrix_d** m_out, const Matrix_d* m_in)
00538 {
00539     float scale;
00540 
00541     scale = 1.0 / (double)(m_in->num_rows*m_in->num_cols);
00542     multiply_matrix_by_scalar_d(m_out, m_in, scale);
00543 }
00544 
00566 void shift_matrix_f
00567 (
00568     Matrix_f**       m_out,
00569     const Matrix_f*  m_in
00570 )
00571 {
00572     uint32_t num_rows, num_cols;
00573     uint32_t row, col;
00574     uint32_t half_rows, half_cols;
00575 
00576     Matrix_f* m = NULL;
00577 
00578     num_rows  = m_in->num_rows;
00579     num_cols  = m_in->num_cols;
00580     half_rows = num_rows / 2;
00581     half_cols = num_cols / 2;
00582 
00583     m = (*m_out == m_in) ? NULL : *m_out;
00584     create_matrix_f(&m, num_rows, num_cols);
00585 
00586     for (row = 0; row < num_rows; row++)
00587     {
00588         if (row < half_rows + (num_rows % 2))
00589         {
00590             for (col = 0; col < num_cols; col++)
00591             {
00592                 if (col < half_cols + (num_cols % 2))
00593                 {
00594                     m->elts[ row ][ col ] = m_in->elts
00595                         [ row + half_rows ]
00596                         [ col + half_cols ];
00597                 }
00598                 else
00599                 {
00600                     m->elts[ row ][ col ] = m_in->elts
00601                         [ row + half_rows ]
00602                         [ col-half_cols-(num_cols % 2) ];
00603                 }
00604             }
00605         }
00606         else
00607         {
00608             for (col = 0; col < num_cols; col++)
00609             {
00610                 if (col < half_cols + (num_cols % 2))
00611                 {
00612                     m->elts[ row ][ col ] = m_in->elts
00613                         [ row - half_rows - (num_rows % 2) ]
00614                         [ col + half_cols ];
00615                 }
00616                 else
00617                 {
00618                     m->elts[ row ][ col ] = m_in->elts
00619                         [ row - half_rows - (num_rows % 2) ]
00620                         [ col - half_cols - (num_cols % 2) ];
00621                 }
00622             }
00623         }
00624     }
00625 
00626     if (*m_out == m_in)
00627     {
00628         copy_matrix_f(m_out, m);
00629         free_matrix_f(m);
00630     }
00631     else
00632     {
00633         *m_out = m;
00634     }
00635 }
00636 
00646 void shift_matrix_d
00647 (
00648     Matrix_d**       m_out,
00649     const Matrix_d*  m_in
00650 )
00651 {
00652     uint32_t num_rows, num_cols;
00653     uint32_t row, col;
00654     uint32_t half_rows, half_cols;
00655 
00656     Matrix_d* m = NULL;
00657 
00658     num_rows  = m_in->num_rows;
00659     num_cols  = m_in->num_cols;
00660     half_rows = num_rows / 2;
00661     half_cols = num_cols / 2;
00662 
00663     m = (*m_out == m_in) ? NULL : *m_out;
00664     create_matrix_d(&m, num_rows, num_cols);
00665 
00666     for (row = 0; row < num_rows; row++)
00667     {
00668         if (row < half_rows + (num_rows % 2))
00669         {
00670             for (col = 0; col < num_cols; col++)
00671             {
00672                 if (col < half_cols + (num_cols % 2))
00673                 {
00674                     m->elts[ row ][ col ] = m_in->elts
00675                         [ row + half_rows ]
00676                         [ col + half_cols ];
00677                 }
00678                 else
00679                 {
00680                     m->elts[ row ][ col ] = m_in->elts
00681                         [ row + half_rows ]
00682                         [ col-half_cols-(num_cols % 2) ];
00683                 }
00684             }
00685         }
00686         else
00687         {
00688             for (col = 0; col < num_cols; col++)
00689             {
00690                 if (col < half_cols + (num_cols % 2))
00691                 {
00692                     m->elts[ row ][ col ] = m_in->elts
00693                         [ row - half_rows - (num_rows % 2) ]
00694                         [ col + half_cols ];
00695                 }
00696                 else
00697                 {
00698                     m->elts[ row ][ col ] = m_in->elts
00699                         [ row - half_rows - (num_rows % 2) ]
00700                         [ col - half_cols - (num_cols % 2) ];
00701                 }
00702             }
00703         }
00704     }
00705 
00706     if (*m_out == m_in)
00707     {
00708         copy_matrix_d(m_out, m);
00709         free_matrix_d(m);
00710     }
00711     else
00712     {
00713         *m_out = m;
00714     }
00715 }
00716 
00726 void shift_matrix_cf
00727 (
00728     Matrix_cf**       m_out,
00729     const Matrix_cf*  m_in
00730 )
00731 {
00732     uint32_t num_rows, num_cols;
00733     uint32_t row, col;
00734     uint32_t half_rows, half_cols;
00735 
00736     Matrix_cf* m = NULL;
00737 
00738     num_rows  = m_in->num_rows;
00739     num_cols  = m_in->num_cols;
00740     half_rows = num_rows / 2;
00741     half_cols = num_cols / 2;
00742 
00743     m = (*m_out == m_in) ? NULL : *m_out;
00744     create_matrix_cf(&m, num_rows, num_cols);
00745 
00746     for (row = 0; row < num_rows; row++)
00747     {
00748         if (row < half_rows + (num_rows % 2))
00749         {
00750             for (col = 0; col < num_cols; col++)
00751             {
00752                 if (col < half_cols + (num_cols % 2))
00753                 {
00754                     m->elts[ row ][ col ] = m_in->elts
00755                         [ row + half_rows ]
00756                         [ col + half_cols ];
00757                 }
00758                 else
00759                 {
00760                     m->elts[ row ][ col ] = m_in->elts
00761                         [ row + half_rows ]
00762                         [ col-half_cols-(num_cols % 2) ];
00763                 }
00764             }
00765         }
00766         else
00767         {
00768             for (col = 0; col < num_cols; col++)
00769             {
00770                 if (col < half_cols + (num_cols % 2))
00771                 {
00772                     m->elts[ row ][ col ] = m_in->elts
00773                         [ row - half_rows - (num_rows % 2) ]
00774                         [ col + half_cols ];
00775                 }
00776                 else
00777                 {
00778                     m->elts[ row ][ col ] = m_in->elts
00779                         [ row - half_rows - (num_rows % 2) ]
00780                         [ col - half_cols - (num_cols % 2) ];
00781                 }
00782             }
00783         }
00784     }
00785 
00786     if (*m_out == m_in)
00787     {
00788         copy_matrix_cf(m_out, m);
00789         free_matrix_cf(m);
00790     }
00791     else
00792     {
00793         *m_out = m;
00794     }
00795 }
00796 
00806 void shift_matrix_cd
00807 (
00808     Matrix_cd**       m_out,
00809     const Matrix_cd*  m_in
00810 )
00811 {
00812     uint32_t num_rows, num_cols;
00813     uint32_t row, col;
00814     uint32_t half_rows, half_cols;
00815 
00816     Matrix_cd* m = NULL;
00817 
00818     num_rows  = m_in->num_rows;
00819     num_cols  = m_in->num_cols;
00820     half_rows = num_rows / 2;
00821     half_cols = num_cols / 2;
00822 
00823     m = (*m_out == m_in) ? NULL : *m_out;
00824     create_matrix_cd(&m, num_rows, num_cols);
00825 
00826     for (row = 0; row < num_rows; row++)
00827     {
00828         if (row < half_rows + (num_rows % 2))
00829         {
00830             for (col = 0; col < num_cols; col++)
00831             {
00832                 if (col < half_cols + (num_cols % 2))
00833                 {
00834                     m->elts[ row ][ col ] = m_in->elts
00835                         [ row + half_rows ]
00836                         [ col + half_cols ];
00837                 }
00838                 else
00839                 {
00840                     m->elts[ row ][ col ] = m_in->elts
00841                         [ row + half_rows ]
00842                         [ col-half_cols-(num_cols % 2) ];
00843                 }
00844             }
00845         }
00846         else
00847         {
00848             for (col = 0; col < num_cols; col++)
00849             {
00850                 if (col < half_cols + (num_cols % 2))
00851                 {
00852                     m->elts[ row ][ col ] = m_in->elts
00853                         [ row - half_rows - (num_rows % 2) ]
00854                         [ col + half_cols ];
00855                 }
00856                 else
00857                 {
00858                     m->elts[ row ][ col ] = m_in->elts
00859                         [ row - half_rows - (num_rows % 2) ]
00860                         [ col - half_cols - (num_cols % 2) ];
00861                 }
00862             }
00863         }
00864     }
00865 
00866     if (*m_out == m_in)
00867     {
00868         copy_matrix_cd(m_out, m);
00869         free_matrix_cd(m);
00870     }
00871     else
00872     {
00873         *m_out = m;
00874     }
00875 }
00876 
00898 void unshift_matrix_f
00899 (
00900     Matrix_f**       m_out,
00901     const Matrix_f*  m_in
00902 )
00903 {
00904     uint32_t num_rows, num_cols;
00905     uint32_t row, col;
00906     uint32_t half_rows, half_cols;
00907 
00908     Matrix_f* m = NULL;
00909 
00910     num_rows  = m_in->num_rows;
00911     num_cols  = m_in->num_cols;
00912     half_rows = num_rows / 2;
00913     half_cols = num_cols / 2;
00914 
00915     m = (*m_out == m_in) ? NULL : *m_out;
00916     create_matrix_f(&m, num_rows, num_cols);
00917 
00918     for (row = 0; row < num_rows; row++)
00919     {
00920         if (row < half_rows)
00921         {
00922             for (col = 0; col < num_cols; col++)
00923             {
00924                 if (col < half_cols)
00925                 {
00926                     m->elts[ row ][ col ] = m_in->elts
00927                         [ row + half_rows + (num_rows % 2) ]
00928                         [ col + half_cols + (num_cols % 2) ];
00929                 }
00930                 else
00931                 {
00932                     m->elts[ row ][ col ] = m_in->elts
00933                         [ row + half_rows + (num_rows % 2) ]
00934                         [ col - half_cols ];
00935                 }
00936             }
00937         }
00938         else
00939         {
00940             for (col = 0; col < num_cols; col++)
00941             {
00942                 if (col < half_cols)
00943                 {
00944                     m->elts[ row ][ col ] = m_in->elts
00945                         [ row - half_rows ]
00946                         [ col + half_cols + (num_cols % 2) ];
00947                 }
00948                 else
00949                 {
00950                     m->elts[ row ][ col ] = m_in->elts
00951                         [ row - half_rows]
00952                         [ col - half_cols];
00953                 }
00954             }
00955         }
00956     }
00957 
00958     if (*m_out == m_in)
00959     {
00960         copy_matrix_f(m_out, m);
00961         free_matrix_f(m);
00962     }
00963     else
00964     {
00965         *m_out = m;
00966     }
00967 }
00968 
00978 void unshift_matrix_d
00979 (
00980     Matrix_d**       m_out,
00981     const Matrix_d*  m_in
00982 )
00983 {
00984     uint32_t num_rows, num_cols;
00985     uint32_t row, col;
00986     uint32_t half_rows, half_cols;
00987 
00988     Matrix_d* m = NULL;
00989 
00990     num_rows  = m_in->num_rows;
00991     num_cols  = m_in->num_cols;
00992     half_rows = num_rows / 2;
00993     half_cols = num_cols / 2;
00994 
00995     m = (*m_out == m_in) ? NULL : *m_out;
00996     create_matrix_d(&m, num_rows, num_cols);
00997 
00998     for (row = 0; row < num_rows; row++)
00999     {
01000         if (row < half_rows)
01001         {
01002             for (col = 0; col < num_cols; col++)
01003             {
01004                 if (col < half_cols)
01005                 {
01006                     m->elts[ row ][ col ] = m_in->elts
01007                         [ row + half_rows + (num_rows % 2) ]
01008                         [ col + half_cols + (num_cols % 2) ];
01009                 }
01010                 else
01011                 {
01012                     m->elts[ row ][ col ] = m_in->elts
01013                         [ row + half_rows + (num_rows % 2) ]
01014                         [ col - half_cols ];
01015                 }
01016             }
01017         }
01018         else
01019         {
01020             for (col = 0; col < num_cols; col++)
01021             {
01022                 if (col < half_cols)
01023                 {
01024                     m->elts[ row ][ col ] = m_in->elts
01025                         [ row - half_rows ]
01026                         [ col + half_cols + (num_cols % 2) ];
01027                 }
01028                 else
01029                 {
01030                     m->elts[ row ][ col ] = m_in->elts
01031                         [ row - half_rows]
01032                         [ col - half_cols];
01033                 }
01034             }
01035         }
01036     }
01037 
01038     if (*m_out == m_in)
01039     {
01040         copy_matrix_d(m_out, m);
01041         free_matrix_d(m);
01042     }
01043     else
01044     {
01045         *m_out = m;
01046     }
01047 }
01048 
01058 void unshift_matrix_cf
01059 (
01060     Matrix_cf**       m_out,
01061     const Matrix_cf*  m_in
01062 )
01063 {
01064     uint32_t num_rows, num_cols;
01065     uint32_t row, col;
01066     uint32_t half_rows, half_cols;
01067 
01068     Matrix_cf* m = NULL;
01069 
01070     num_rows  = m_in->num_rows;
01071     num_cols  = m_in->num_cols;
01072     half_rows = num_rows / 2;
01073     half_cols = num_cols / 2;
01074 
01075     m = (*m_out == m_in) ? NULL : *m_out;
01076     create_matrix_cf(&m, num_rows, num_cols);
01077 
01078     for (row = 0; row < num_rows; row++)
01079     {
01080         if (row < half_rows)
01081         {
01082             for (col = 0; col < num_cols; col++)
01083             {
01084                 if (col < half_cols)
01085                 {
01086                     m->elts[ row ][ col ] = m_in->elts
01087                         [ row + half_rows + (num_rows % 2) ]
01088                         [ col + half_cols + (num_cols % 2) ];
01089                 }
01090                 else
01091                 {
01092                     m->elts[ row ][ col ] = m_in->elts
01093                         [ row + half_rows + (num_rows % 2) ]
01094                         [ col - half_cols ];
01095                 }
01096             }
01097         }
01098         else
01099         {
01100             for (col = 0; col < num_cols; col++)
01101             {
01102                 if (col < half_cols)
01103                 {
01104                     m->elts[ row ][ col ] = m_in->elts
01105                         [ row - half_rows ]
01106                         [ col + half_cols + (num_cols % 2) ];
01107                 }
01108                 else
01109                 {
01110                     m->elts[ row ][ col ] = m_in->elts
01111                         [ row - half_rows]
01112                         [ col - half_cols];
01113                 }
01114             }
01115         }
01116     }
01117 
01118     if (*m_out == m_in)
01119     {
01120         copy_matrix_cf(m_out, m);
01121         free_matrix_cf(m);
01122     }
01123     else
01124     {
01125         *m_out = m;
01126     }
01127 }
01128 
01138 void unshift_matrix_cd
01139 (
01140     Matrix_cd**       m_out,
01141     const Matrix_cd*  m_in
01142 )
01143 {
01144     uint32_t num_rows, num_cols;
01145     uint32_t row, col;
01146     uint32_t half_rows, half_cols;
01147 
01148     Matrix_cd* m = NULL;
01149 
01150     num_rows  = m_in->num_rows;
01151     num_cols  = m_in->num_cols;
01152     half_rows = num_rows / 2;
01153     half_cols = num_cols / 2;
01154 
01155     m = (*m_out == m_in) ? NULL : *m_out;
01156     create_matrix_cd(&m, num_rows, num_cols);
01157 
01158     for (row = 0; row < num_rows; row++)
01159     {
01160         if (row < half_rows)
01161         {
01162             for (col = 0; col < num_cols; col++)
01163             {
01164                 if (col < half_cols)
01165                 {
01166                     m->elts[ row ][ col ] = m_in->elts
01167                         [ row + half_rows + (num_rows % 2) ]
01168                         [ col + half_cols + (num_cols % 2) ];
01169                 }
01170                 else
01171                 {
01172                     m->elts[ row ][ col ] = m_in->elts
01173                         [ row + half_rows + (num_rows % 2) ]
01174                         [ col - half_cols ];
01175                 }
01176             }
01177         }
01178         else
01179         {
01180             for (col = 0; col < num_cols; col++)
01181             {
01182                 if (col < half_cols)
01183                 {
01184                     m->elts[ row ][ col ] = m_in->elts
01185                         [ row - half_rows ]
01186                         [ col + half_cols + (num_cols % 2) ];
01187                 }
01188                 else
01189                 {
01190                     m->elts[ row ][ col ] = m_in->elts
01191                         [ row - half_rows]
01192                         [ col - half_cols];
01193                 }
01194             }
01195         }
01196     }
01197 
01198     if (*m_out == m_in)
01199     {
01200         copy_matrix_cd(m_out, m);
01201         free_matrix_cd(m);
01202     }
01203     else
01204     {
01205         *m_out = m;
01206     }
01207 }
01208