JWS C Library
C language utility library
matblock_math.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 
00049 #include <jwsc/config.h>
00050 
00051 #include <stdlib.h>
00052 #include <assert.h>
00053 #include <math.h>
00054 #include <inttypes.h>
00055 
00056 #include "jwsc/base/error.h"
00057 #include "jwsc/math/complex.h"
00058 #include "jwsc/math/blas.h"
00059 #include "jwsc/matblock/matblock.h"
00060 #include "jwsc/matblock/matblock_math.h"
00061 
00062 
00078 void add_scalar_to_matblock_f
00079 (
00080     Matblock_f**      m_out, 
00081     const Matblock_f* m_in, 
00082     float             a
00083 )
00084 {
00085     uint32_t  num_elts;
00086     uint32_t  elt;
00087     float*    m_in_elts;
00088     float*    m_out_elts;
00089 
00090     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
00091 
00092     if (*m_out != m_in)
00093     {
00094         create_matblock_f(m_out, m_in->num_mats, m_in->num_rows, 
00095                 m_in->num_cols);
00096     }
00097     m_out_elts = **((*m_out)->elts);
00098     m_in_elts  = **(m_in->elts);
00099 
00100     for (elt = 0; elt < num_elts; elt++)
00101     {
00102         m_out_elts[ elt ] = a + m_in_elts[ elt ];
00103     }
00104 }
00105 
00114 void add_scalar_to_matblock_d
00115 (
00116     Matblock_d**      m_out, 
00117     const Matblock_d* m_in, 
00118     double            a
00119 )
00120 {
00121     uint32_t  num_elts;
00122     uint32_t  elt;
00123     double*   m_in_elts;
00124     double*   m_out_elts;
00125 
00126     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
00127 
00128     if (*m_out != m_in)
00129     {
00130         create_matblock_d(m_out, m_in->num_mats, m_in->num_rows, 
00131                 m_in->num_cols);
00132     }
00133     m_out_elts = **((*m_out)->elts);
00134     m_in_elts  = **(m_in->elts);
00135 
00136     for (elt = 0; elt < num_elts; elt++)
00137     {
00138         m_out_elts[ elt ] = a + m_in_elts[ elt ];
00139     }
00140 }
00141 
00150 void add_scalar_to_matblock_cf
00151 (
00152     Matblock_cf**      m_out, 
00153     const Matblock_cf* m_in, 
00154     Complex_f          z
00155 )
00156 {
00157     uint32_t   num_elts;
00158     uint32_t   elt;
00159     Complex_f* m_in_elts;
00160     Complex_f* m_out_elts;
00161 
00162     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
00163 
00164     if (*m_out != m_in)
00165     {
00166         create_matblock_cf(m_out, m_in->num_mats, m_in->num_rows, 
00167                 m_in->num_cols);
00168     }
00169     m_out_elts = **((*m_out)->elts);
00170     m_in_elts  = **(m_in->elts);
00171 
00172     for (elt = 0; elt < num_elts; elt++)
00173     {
00174         m_out_elts[ elt ].r = z.r + m_in_elts[ elt ].r;
00175         m_out_elts[ elt ].i = z.i + m_in_elts[ elt ].i;
00176     }
00177 }
00178 
00187 void add_scalar_to_matblock_cd
00188 (
00189     Matblock_cd**      m_out, 
00190     const Matblock_cd* m_in, 
00191     Complex_d          z
00192 )
00193 {
00194     uint32_t   num_elts;
00195     uint32_t   elt;
00196     Complex_d* m_in_elts;
00197     Complex_d* m_out_elts;
00198 
00199     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
00200 
00201     if (*m_out != m_in)
00202     {
00203         create_matblock_cd(m_out, m_in->num_mats, m_in->num_rows, 
00204                 m_in->num_cols);
00205     }
00206     m_out_elts = **((*m_out)->elts);
00207     m_in_elts  = **(m_in->elts);
00208 
00209     for (elt = 0; elt < num_elts; elt++)
00210     {
00211         m_out_elts[ elt ].r = z.r + m_in_elts[ elt ].r;
00212         m_out_elts[ elt ].i = z.i + m_in_elts[ elt ].i;
00213     }
00214 }
00215 
00236 void multiply_matblock_by_scalar_f
00237 (
00238     Matblock_f**      m_out, 
00239     const Matblock_f* m_in, 
00240     float             a
00241 )
00242 {
00243     uint32_t num_elts;
00244 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00245 #else
00246     uint32_t elt;
00247     float*   m_out_elts;
00248     float*   m_in_elts;
00249 #endif
00250 
00251     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
00252 
00253 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00254     if (*m_out != m_in)
00255     {
00256         copy_matblock_f(m_out, m_in);
00257     }
00258 
00259     blas_sscal(num_elts, a, **((*m_out)->elts), 1);
00260 #else
00261     if (*m_out != m_in)
00262     {
00263         create_matblock_f(m_out, m_in->num_mats, m_in->num_rows, 
00264                 m_in->num_cols);
00265     }
00266 
00267     m_out_elts = **((*m_out)->elts);
00268     m_in_elts  = **(m_in->elts);
00269 
00270     for (elt = 0; elt < num_elts; elt++)
00271     {
00272         m_out_elts[ elt ] = a * m_in_elts[ elt ];
00273     }
00274 #endif
00275 }
00276 
00285 void multiply_matblock_by_scalar_d
00286 (
00287     Matblock_d**      m_out, 
00288     const Matblock_d* m_in, 
00289     double            a
00290 )
00291 {
00292     uint32_t num_elts;
00293 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00294 #else
00295     uint32_t elt;
00296     double*  m_out_elts;
00297     double*  m_in_elts;
00298 #endif
00299 
00300     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
00301 
00302 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00303     if (*m_out != m_in)
00304     {
00305         copy_matblock_d(m_out, m_in);
00306     }
00307 
00308     blas_dscal(num_elts, a, **((*m_out)->elts), 1);
00309 #else
00310     if (*m_out != m_in)
00311     {
00312         create_matblock_d(m_out, m_in->num_mats, m_in->num_rows, 
00313                 m_in->num_cols);
00314     }
00315 
00316     m_out_elts = **((*m_out)->elts);
00317     m_in_elts  = **(m_in->elts);
00318 
00319     for (elt = 0; elt < num_elts; elt++)
00320     {
00321         m_out_elts[ elt ] = a * m_in_elts[ elt ];
00322     }
00323 #endif
00324 }
00325 
00334 void multiply_matblock_by_scalar_cf
00335 (
00336     Matblock_cf**      m_out, 
00337     const Matblock_cf* m_in, 
00338     Complex_f          z
00339 )
00340 {
00341     uint32_t num_elts;
00342 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00343 #else
00344     uint32_t   elt;
00345     float      r, i;
00346     Complex_f* m_out_elts;
00347     Complex_f* m_in_elts;
00348 #endif
00349 
00350     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
00351 
00352 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00353     if (*m_out != m_in)
00354     {
00355         copy_matblock_cf(m_out, m_in);
00356     }
00357 
00358     blas_cscal(num_elts, z, **((*m_out)->elts), 1);
00359 #else
00360     if (*m_out != m_in)
00361     {
00362         create_matblock_cf(m_out, m_in->num_mats, m_in->num_rows, 
00363                 m_in->num_cols);
00364     }
00365 
00366     m_out_elts = **((*m_out)->elts);
00367     m_in_elts  = **(m_in->elts);
00368 
00369     for (elt = 0; elt < num_elts; elt++)
00370     {
00371         r = z.r*m_in_elts[ elt ].r - z.i*m_in_elts[ elt ].i;
00372         i = z.i*m_in_elts[ elt ].r + z.r*m_in_elts[ elt ].i;
00373 
00374         m_out_elts[ elt ].r = r;
00375         m_out_elts[ elt ].i = i;
00376     }
00377 #endif
00378 }
00379 
00388 void multiply_matblock_by_scalar_cd
00389 (
00390     Matblock_cd**      m_out, 
00391     const Matblock_cd* m_in, 
00392     Complex_d          z
00393 )
00394 {
00395     uint32_t num_elts;
00396 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00397 #else
00398     uint32_t   elt;
00399     double     r, i;
00400     Complex_d* m_out_elts;
00401     Complex_d* m_in_elts;
00402 #endif
00403 
00404     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
00405 
00406 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00407     if (*m_out != m_in)
00408     {
00409         copy_matblock_cd(m_out, m_in);
00410     }
00411 
00412     blas_zscal(num_elts, z, **((*m_out)->elts), 1);
00413 #else
00414     if (*m_out != m_in)
00415     {
00416         create_matblock_cd(m_out, m_in->num_mats, m_in->num_rows, 
00417                 m_in->num_cols);
00418     }
00419 
00420     m_out_elts = **((*m_out)->elts);
00421     m_in_elts  = **(m_in->elts);
00422 
00423     for (elt = 0; elt < num_elts; elt++)
00424     {
00425         r = z.r*m_in_elts[ elt ].r - z.i*m_in_elts[ elt ].i;
00426         i = z.i*m_in_elts[ elt ].r + z.r*m_in_elts[ elt ].i;
00427 
00428         m_out_elts[ elt ].r = r;
00429         m_out_elts[ elt ].i = i;
00430     }
00431 #endif
00432 }
00433 
00461 Error* multiply_matblocks_elt_wise_f
00462 (
00463     Matblock_f**      m_out, 
00464     const Matblock_f* m_1, 
00465     const Matblock_f* m_2
00466 )
00467 {
00468     uint32_t  num_mats, num_rows, num_cols;
00469     uint32_t  num_elts;
00470     uint32_t  elt;
00471     float*    m_out_elts;
00472     float*    m_1_elts;
00473     float*    m_2_elts;
00474 
00475     num_mats = m_1->num_mats;
00476     num_rows = m_1->num_rows;
00477     num_cols = m_1->num_cols;
00478 
00479     if (num_mats != m_2->num_mats || 
00480         num_rows != m_2->num_rows ||
00481         num_cols != m_2->num_cols)
00482     {
00483         if (*m_out != m_1 && *m_out != m_2)
00484         {
00485             free_matblock_f(*m_out); *m_out = NULL;
00486         }
00487         return JWSC_EARG("Matblocks do not have the same dimensions");
00488     }
00489 
00490     m_out_elts = **((*m_out)->elts);
00491     m_1_elts   = **(m_1->elts);
00492     m_2_elts   = **(m_2->elts);
00493 
00494     num_elts = num_mats*num_rows*num_cols;
00495     for (elt = 0; elt < num_elts; elt++)
00496     {
00497         m_out_elts[ elt ] = m_1_elts[ elt ]*m_2_elts[ elt ];
00498     }
00499 
00500     return NULL;
00501 }
00502 
00503 Error* multiply_matblocks_elt_wise_d
00504 (
00505     Matblock_d**      m_out, 
00506     const Matblock_d* m_1, 
00507     const Matblock_d* m_2
00508 )
00509 {
00510     uint32_t  num_mats, num_rows, num_cols;
00511     uint32_t  num_elts;
00512     uint32_t  elt;
00513     double*   m_out_elts;
00514     double*   m_1_elts;
00515     double*   m_2_elts;
00516 
00517     num_mats = m_1->num_mats;
00518     num_rows = m_1->num_rows;
00519     num_cols = m_1->num_cols;
00520 
00521     if (num_mats != m_2->num_mats || 
00522         num_rows != m_2->num_rows ||
00523         num_cols != m_2->num_cols)
00524     {
00525         if (*m_out != m_1 && *m_out != m_2)
00526         {
00527             free_matblock_d(*m_out); *m_out = NULL;
00528         }
00529         return JWSC_EARG("Matblocks do not have the same dimensions");
00530     }
00531 
00532     m_out_elts = **((*m_out)->elts);
00533     m_1_elts   = **(m_1->elts);
00534     m_2_elts   = **(m_2->elts);
00535 
00536     num_elts = num_mats*num_rows*num_cols;
00537     for (elt = 0; elt < num_elts; elt++)
00538     {
00539         m_out_elts[ elt ] = m_1_elts[ elt ]*m_2_elts[ elt ];
00540     }
00541 
00542     return NULL;
00543 }
00544 
00545 Error* multiply_matblocks_elt_wise_cf
00546 (
00547     Matblock_cf**      m_out, 
00548     const Matblock_cf* m_1, 
00549     const Matblock_cf* m_2
00550 )
00551 {
00552     uint32_t   num_mats, num_rows, num_cols;
00553     uint32_t   num_elts;
00554     uint32_t   elt;
00555     float      r, i;
00556     Complex_f* m_out_elts;
00557     Complex_f* m_1_elts;
00558     Complex_f* m_2_elts;
00559 
00560     num_mats = m_1->num_mats;
00561     num_rows = m_1->num_rows;
00562     num_cols = m_1->num_cols;
00563 
00564     if (num_mats != m_2->num_mats || 
00565         num_rows != m_2->num_rows ||
00566         num_cols != m_2->num_cols)
00567     {
00568         if (*m_out != m_1 && *m_out != m_2)
00569         {
00570             free_matblock_cf(*m_out); *m_out = NULL;
00571         }
00572         return JWSC_EARG("Matblocks do not have the same dimensions");
00573     }
00574 
00575     m_out_elts = **((*m_out)->elts);
00576     m_1_elts   = **(m_1->elts);
00577     m_2_elts   = **(m_2->elts);
00578 
00579     num_elts = num_mats*num_rows*num_cols;
00580     for (elt = 0; elt < num_elts; elt++)
00581     {
00582         r = m_1_elts[ elt ].r * m_2_elts[ elt ].r -
00583             m_1_elts[ elt ].i * m_2_elts[ elt ].i;
00584         i = m_1_elts[ elt ].i * m_2_elts[ elt ].r +
00585             m_1_elts[ elt ].r * m_2_elts[ elt ].i;
00586 
00587         m_out_elts[ elt ].r = r;
00588         m_out_elts[ elt ].i = i;
00589     }
00590 
00591     return NULL;
00592 }
00593 
00594 Error* multiply_matblocks_elt_wise_cd
00595 (
00596     Matblock_cd**      m_out, 
00597     const Matblock_cd* m_1, 
00598     const Matblock_cd* m_2
00599 )
00600 {
00601     uint32_t   num_mats, num_rows, num_cols;
00602     uint32_t   num_elts;
00603     uint32_t   elt;
00604     double     r, i;
00605     Complex_d* m_out_elts;
00606     Complex_d* m_1_elts;
00607     Complex_d* m_2_elts;
00608 
00609     num_mats = m_1->num_mats;
00610     num_rows = m_1->num_rows;
00611     num_cols = m_1->num_cols;
00612 
00613     if (num_mats != m_2->num_mats || 
00614         num_rows != m_2->num_rows ||
00615         num_cols != m_2->num_cols)
00616     {
00617         if (*m_out != m_1 && *m_out != m_2)
00618         {
00619             free_matblock_cd(*m_out); *m_out = NULL;
00620         }
00621         return JWSC_EARG("Matblocks do not have the same dimensions");
00622     }
00623 
00624     m_out_elts = **((*m_out)->elts);
00625     m_1_elts   = **(m_1->elts);
00626     m_2_elts   = **(m_2->elts);
00627 
00628     num_elts = num_mats*num_rows*num_cols;
00629     for (elt = 0; elt < num_elts; elt++)
00630     {
00631         r = m_1_elts[ elt ].r * m_2_elts[ elt ].r -
00632             m_1_elts[ elt ].i * m_2_elts[ elt ].i;
00633         i = m_1_elts[ elt ].i * m_2_elts[ elt ].r +
00634             m_1_elts[ elt ].r * m_2_elts[ elt ].i;
00635 
00636         m_out_elts[ elt ].r = r;
00637         m_out_elts[ elt ].i = i;
00638     }
00639 
00640     return NULL;
00641 }
00642 
00670 Error* add_matblocks_f
00671 (
00672     Matblock_f**      m_out, 
00673     const Matblock_f* m_1, 
00674     const Matblock_f* m_2
00675 )
00676 {
00677     uint32_t num_elts;
00678 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00679 #else
00680     uint32_t elt;
00681     float*   m_1_elts;
00682     float*   m_2_elts;
00683     float*   m_out_elts;
00684 #endif
00685 
00686     if (m_1->num_mats != m_2->num_mats ||
00687         m_1->num_rows != m_2->num_rows || 
00688         m_1->num_cols != m_2->num_cols)
00689     {
00690         if (*m_out != m_1 && *m_out != m_2)
00691         {
00692             free_matblock_f(*m_out); *m_out = NULL;
00693         }
00694         return JWSC_EARG("Adding matblocks requires equal dimensions");
00695     }
00696 
00697     num_elts = m_1->num_mats*m_1->num_rows*m_1->num_cols;
00698 
00699 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00700     if (*m_out == m_1)
00701     {
00702         blas_saxpy(num_elts, 1, **(m_2->elts), 1, **(m_1->elts), 1);
00703     }
00704     else if (*m_out == m_2)
00705     {
00706         blas_saxpy(num_elts, 1, **(m_1->elts), 1, **(m_2->elts), 1);
00707     }
00708     else
00709     {
00710         copy_matblock_f(m_out, m_2);
00711         blas_saxpy(num_elts, 1, **(m_1->elts), 1, **((*m_out)->elts), 1);
00712     }
00713 #else
00714     m_1_elts   = **(m_1->elts);
00715     m_2_elts   = **(m_2->elts);
00716     m_out_elts = **((*m_out)->elts);
00717 
00718     if (*m_out == m_1)
00719     {
00720         for (elt = 0; elt < num_elts; elt++)
00721         {
00722             m_1_elts[ elt ] += m_2_elts[ elt ];
00723         }
00724     }
00725     else if (*m_out == m_2)
00726     {
00727         for (elt = 0; elt < num_elts; elt++)
00728         {
00729             m_2_elts[ elt ] += m_1_elts[ elt ];
00730         }
00731     }
00732     else
00733     {
00734         create_matblock_f(m_out, m_1->num_cols, m_1->num_rows, m_1->num_cols);
00735         for (elt = 0; elt < num_elts; elt++)
00736         {
00737             m_out_elts[ elt ] = m_1_elts[ elt ] + m_2_elts[ elt ];
00738         }
00739     }
00740 #endif
00741 
00742     return NULL;
00743 }
00744 
00760 Error* add_matblocks_d
00761 (
00762     Matblock_d**      m_out, 
00763     const Matblock_d* m_1, 
00764     const Matblock_d* m_2
00765 )
00766 {
00767     uint32_t num_elts;
00768 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00769 #else
00770     uint32_t elt;
00771     double*  m_1_elts;
00772     double*  m_2_elts;
00773     double*  m_out_elts;
00774 #endif
00775 
00776     if (m_1->num_mats != m_2->num_mats ||
00777         m_1->num_rows != m_2->num_rows || 
00778         m_1->num_cols != m_2->num_cols)
00779     {
00780         if (*m_out != m_1 && *m_out != m_2)
00781         {
00782             free_matblock_d(*m_out); *m_out = NULL;
00783         }
00784         return JWSC_EARG("Adding matblocks requires equal dimensions");
00785     }
00786 
00787     num_elts = m_1->num_mats*m_1->num_rows*m_1->num_cols;
00788 
00789 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00790     if (*m_out == m_1)
00791     {
00792         blas_daxpy(num_elts, 1, **(m_2->elts), 1, **(m_1->elts), 1);
00793     }
00794     else if (*m_out == m_2)
00795     {
00796         blas_daxpy(num_elts, 1, **(m_1->elts), 1, **(m_2->elts), 1);
00797     }
00798     else
00799     {
00800         copy_matblock_d(m_out, m_2);
00801         blas_daxpy(num_elts, 1, **(m_1->elts), 1, **((*m_out)->elts), 1);
00802     }
00803 #else
00804     m_1_elts   = **(m_1->elts);
00805     m_2_elts   = **(m_2->elts);
00806     m_out_elts = **((*m_out)->elts);
00807 
00808     if (*m_out == m_1)
00809     {
00810         for (elt = 0; elt < num_elts; elt++)
00811         {
00812             m_1_elts[ elt ] += m_2_elts[ elt ];
00813         }
00814     }
00815     else if (*m_out == m_2)
00816     {
00817         for (elt = 0; elt < num_elts; elt++)
00818         {
00819             m_2_elts[ elt ] += m_1_elts[ elt ];
00820         }
00821     }
00822     else
00823     {
00824         create_matblock_d(m_out, m_1->num_cols, m_1->num_rows, m_1->num_cols);
00825         for (elt = 0; elt < num_elts; elt++)
00826         {
00827             m_out_elts[ elt ] = m_1_elts[ elt ] + m_2_elts[ elt ];
00828         }
00829     }
00830 #endif
00831 
00832     return NULL;
00833 }
00834 
00862 Error* subtract_matblocks_f
00863 (
00864     Matblock_f**      m_out, 
00865     const Matblock_f* m_1, 
00866     const Matblock_f* m_2
00867 )
00868 {
00869     uint32_t num_elts;
00870 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00871     Matblock_f* m = NULL;
00872 #else
00873     uint32_t elt;
00874     float*   m_1_elts;
00875     float*   m_2_elts;
00876     float*   m_out_elts;
00877 #endif
00878 
00879     if (m_1->num_mats != m_2->num_mats ||
00880         m_1->num_rows != m_2->num_rows || 
00881         m_1->num_cols != m_2->num_cols)
00882     {
00883         if (*m_out != m_1 && *m_out != m_2)
00884         {
00885             free_matblock_f(*m_out); *m_out = NULL;
00886         }
00887         return JWSC_EARG("Subtracting matblocks requires equal dimensions");
00888     }
00889 
00890     num_elts = m_1->num_mats*m_1->num_rows*m_1->num_cols;
00891 
00892 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00893     if (*m_out == m_1)
00894     {
00895         blas_saxpy(num_elts, -1, **(m_2->elts), 1, **(m_1->elts), 1);
00896     }
00897     else if (*m_out == m_2)
00898     {
00899         copy_matblock_f(&m, m_1);
00900         blas_saxpy(num_elts, -1, **(m_2->elts), 1, **(m->elts), 1);
00901         copy_matblock_f(m_out, m);
00902         free_matblock_f(m);
00903     }
00904     else
00905     {
00906         copy_matblock_f(m_out, m_1);
00907         blas_saxpy(num_elts, -1, **(m_2->elts), 1, **((*m_out)->elts), 1);
00908     }
00909 #else
00910     m_1_elts   = **(m_1->elts);
00911     m_2_elts   = **(m_2->elts);
00912     m_out_elts = **((*m_out)->elts);
00913 
00914     if (*m_out == m_1)
00915     {
00916         for (elt = 0; elt < num_elts; elt++)
00917         {
00918             m_1_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ];
00919         }
00920     }
00921     else if (*m_out == m_2)
00922     {
00923         for (elt = 0; elt < num_elts; elt++)
00924         {
00925             m_2_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ];
00926         }
00927     }
00928     else
00929     {
00930         create_matblock_f(m_out, m_1->num_mats, m_1->num_rows, m_1->num_cols);
00931         for (elt = 0; elt < num_elts; elt++)
00932         {
00933             m_out_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ];
00934         }
00935     }
00936 #endif
00937 
00938     return NULL;
00939 }
00940 
00956 Error* subtract_matblocks_d
00957 (
00958     Matblock_d**      m_out, 
00959     const Matblock_d* m_1, 
00960     const Matblock_d* m_2
00961 )
00962 {
00963     uint32_t num_elts;
00964 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00965     Matblock_d* m = NULL;
00966 #else
00967     uint32_t elt;
00968     double*  m_1_elts;
00969     double*  m_2_elts;
00970     double*  m_out_elts;
00971 #endif
00972 
00973     if (m_1->num_mats != m_2->num_mats ||
00974         m_1->num_rows != m_2->num_rows || 
00975         m_1->num_cols != m_2->num_cols)
00976     {
00977         if (*m_out != m_1 && *m_out != m_2)
00978         {
00979             free_matblock_d(*m_out); *m_out = NULL;
00980         }
00981         return JWSC_EARG("Subtracting matblocks requires equal dimensions");
00982     }
00983 
00984     num_elts = m_1->num_mats*m_1->num_rows*m_1->num_cols;
00985 
00986 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
00987     if (*m_out == m_1)
00988     {
00989         blas_daxpy(num_elts, -1, **(m_2->elts), 1, **(m_1->elts), 1);
00990     }
00991     else if (*m_out == m_2)
00992     {
00993         copy_matblock_d(&m, m_1);
00994         blas_daxpy(num_elts, -1, **(m_2->elts), 1, **(m->elts), 1);
00995         copy_matblock_d(m_out, m);
00996         free_matblock_d(m);
00997     }
00998     else
00999     {
01000         copy_matblock_d(m_out, m_1);
01001         blas_daxpy(num_elts, -1, **(m_2->elts), 1, **((*m_out)->elts), 1);
01002     }
01003 #else
01004     m_1_elts   = **(m_1->elts);
01005     m_2_elts   = **(m_2->elts);
01006     m_out_elts = **((*m_out)->elts);
01007 
01008     if (*m_out == m_1)
01009     {
01010         for (elt = 0; elt < num_elts; elt++)
01011         {
01012             m_1_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ];
01013         }
01014     }
01015     else if (*m_out == m_2)
01016     {
01017         for (elt = 0; elt < num_elts; elt++)
01018         {
01019             m_2_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ];
01020         }
01021     }
01022     else
01023     {
01024         create_matblock_d(m_out, m_1->num_mats, m_1->num_rows, m_1->num_cols);
01025         for (elt = 0; elt < num_elts; elt++)
01026         {
01027             m_out_elts[ elt ] = m_1_elts[ elt ] - m_2_elts[ elt ];
01028         }
01029     }
01030 #endif
01031 
01032     return NULL;
01033 }
01034 
01051 void calc_matblock_asum_f(float* sum_out, const Matblock_f* m)
01052 {
01053 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
01054     *sum_out = blas_sasum(m->num_mats*m->num_rows*m->num_cols, **(m->elts), 1);
01055 #else
01056     uint32_t num_elts;
01057     uint32_t elt;
01058     float*   m_elts;
01059 
01060     num_elts = m->num_mats*m->num_rows*m->num_cols;
01061     m_elts   = **(m->elts);
01062     *sum_out = 0;
01063 
01064     for (elt = 0; elt < num_elts; elt++)
01065     {
01066         (*sum_out) += (float)fabs(m_elts[ elt ]);
01067     }
01068 #endif
01069 }
01070 
01075 void calc_matblock_asum_d(double* sum_out, const Matblock_d* m)
01076 {
01077 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE
01078     *sum_out = blas_dasum(m->num_mats*m->num_rows*m->num_cols, **(m->elts), 1);
01079 #else
01080     uint32_t num_elts;
01081     uint32_t elt;
01082     double*  m_elts;
01083 
01084     num_elts = m->num_mats*m->num_rows*m->num_cols;
01085     m_elts   = **(m->elts);
01086     *sum_out = 0;
01087 
01088     for (elt = 0; elt < num_elts; elt++)
01089     {
01090         (*sum_out) += fabs(m_elts[ elt ]);
01091     }
01092 #endif
01093 }
01094 
01114 void normalize_matblock_sum_f(Matblock_f** m_out, const Matblock_f* m_in)
01115 {
01116     float sum;
01117 
01118     calc_matblock_asum_f(&sum, m_in);
01119 
01120     if (sum > 0)
01121     {
01122         multiply_matblock_by_scalar_f(m_out, m_in, 1.0f / sum);
01123     } 
01124     else 
01125     {
01126         copy_matblock_f(m_out, m_in);
01127     }
01128 }
01129 
01137 void normalize_matblock_sum_d(Matblock_d** m_out, const Matblock_d* m_in)
01138 {
01139     double sum;
01140 
01141     calc_matblock_asum_d(&sum, m_in);
01142 
01143     if (sum > 0)
01144     {
01145         multiply_matblock_by_scalar_d(m_out, m_in, 1.0 / sum);
01146     } 
01147     else 
01148     {
01149         copy_matblock_d(m_out, m_in);
01150     }
01151 }
01152 
01170 void abs_matblock_f(Matblock_f** m_out, const Matblock_f* m_in)
01171 {
01172     uint32_t  num_elts;
01173     uint32_t  elt;
01174     float*    m_in_elts;
01175     float*    m_out_elts;
01176 
01177     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
01178 
01179     if (*m_out != m_in)
01180     {
01181         create_matblock_f(m_out, m_in->num_mats, m_in->num_rows, 
01182                 m_in->num_cols);
01183     }
01184     m_out_elts = **((*m_out)->elts);
01185     m_in_elts  = **(m_in->elts);
01186 
01187     for (elt = 0; elt < num_elts; elt++)
01188     {
01189         m_out_elts[ elt ] = fabs(m_out_elts[ elt ]);
01190     }
01191 }
01192 
01193 
01201 void abs_matblock_d(Matblock_d** m_out, const Matblock_d* m_in)
01202 {
01203     uint32_t  num_elts;
01204     uint32_t  elt;
01205     double*    m_in_elts;
01206     double*    m_out_elts;
01207 
01208     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
01209 
01210     if (*m_out != m_in)
01211     {
01212         create_matblock_d(m_out, m_in->num_mats, m_in->num_rows, 
01213                 m_in->num_cols);
01214     }
01215     m_out_elts = **((*m_out)->elts);
01216     m_in_elts  = **(m_in->elts);
01217 
01218     for (elt = 0; elt < num_elts; elt++)
01219     {
01220         m_out_elts[ elt ] = fabs(m_out_elts[ elt ]);
01221     }
01222 }
01223 
01224 
01243 void threshold_matblock_f(Matblock_f** m_out, const Matblock_f* m_in, float threshold)
01244 {
01245     uint32_t  num_elts;
01246     uint32_t  elt;
01247     float*    m_in_elts;
01248     float*    m_out_elts;
01249 
01250     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
01251 
01252     if (*m_out != m_in)
01253     {
01254         create_matblock_f(m_out, m_in->num_mats, m_in->num_rows, 
01255                 m_in->num_cols);
01256     }
01257     m_out_elts = **((*m_out)->elts);
01258     m_in_elts  = **(m_in->elts);
01259 
01260     for (elt = 0; elt < num_elts; elt++)
01261     {
01262         if(m_out_elts[ elt ] < threshold) 
01263         {
01264             m_out_elts[ elt ] = 0;
01265         }
01266     }
01267 }
01268 
01277 void threshold_matblock_d(Matblock_d** m_out, const Matblock_d* m_in, double threshold)
01278 {
01279     uint32_t  num_elts;
01280     uint32_t  elt;
01281     double *  m_in_elts;
01282     double *  m_out_elts;
01283 
01284     num_elts = m_in->num_mats*m_in->num_rows*m_in->num_cols;
01285 
01286     if (*m_out != m_in)
01287     {
01288         create_matblock_d(m_out, m_in->num_mats, m_in->num_rows, 
01289                 m_in->num_cols);
01290     }
01291     m_out_elts = **((*m_out)->elts);
01292     m_in_elts  = **(m_in->elts);
01293 
01294     for (elt = 0; elt < num_elts; elt++)
01295     {
01296         if(m_out_elts[ elt ] < threshold) 
01297         {
01298             m_out_elts[ elt ] = 0;
01299         }
01300     }
01301 }
01302