JWS C Library
C language utility library
mv_pdf.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 
00046 #include <jwsc/config.h>
00047 
00048 #include <stdlib.h>
00049 #include <stdio.h>
00050 #include <assert.h>
00051 #include <math.h>
00052 #include <inttypes.h>
00053 
00054 #include "jwsc/base/error.h"
00055 #include "jwsc/math/constants.h"
00056 #include "jwsc/math/lapack.h"
00057 #include "jwsc/vector/vector.h"
00058 #include "jwsc/vector/vector_math.h"
00059 #include "jwsc/matrix/matrix.h"
00060 #include "jwsc/matrix/matrix_math.h"
00061 #include "jwsc/prob/pdf.h"
00062 #include "jwsc/prob/mv_pdf.h"
00063 
00064 
00065 #if defined JWSC_HAVE_LAPACK
00066 
00083 Error* mv_gaussian_pdf_f
00084 (
00085     float*          p_out,
00086     const Vector_f* mu, 
00087     const Matrix_f* sigma, 
00088     const Vector_f* x
00089 )
00090 {
00091     uint32_t    D;
00092     float       sigma_det;
00093     float       d;
00094     double      c;
00095     Matrix_f*   sigma_lu = NULL;
00096     Matrix_f*   sigma_inv = NULL;
00097     Vector_i32* pivot = NULL;
00098     Vector_f*   v_1 = NULL;
00099     Vector_f*   v_2 = NULL;
00100     Error*      e;
00101 
00102     D = mu->num_elts;
00103 
00104     if (D != sigma->num_rows || D != sigma->num_cols || D != x->num_elts)
00105     {
00106         return JWSC_EARG("Invalid argument dimensions");
00107     }
00108 
00109     if ((e = lu_decompose_matrix_f(&sigma_lu, &pivot, sigma)) != NULL)
00110     {
00111         free_error(e);
00112         return JWSC_EARG("Covariance matrix is singular");
00113     }
00114 
00115     calc_lu_matrix_determinant_f(&sigma_det, sigma_lu, pivot);
00116 
00117     if (sigma_det < 1.0e-10f)
00118     {
00119         fprintf(stderr, "%e\n", sigma_det);
00120         free_vector_i32(pivot);
00121         free_matrix_f(sigma_lu);
00122         return JWSC_EARG("Invalid covariance matrix");
00123     }
00124 
00125     if ((e = invert_lu_matrix_f(&sigma_inv, sigma_lu, pivot)) != NULL)
00126     {
00127         free_error(e);
00128         free_vector_i32(pivot);
00129         free_matrix_f(sigma_lu);
00130         return JWSC_EARG("Covariance matrix is singular");
00131     }
00132 
00133     c = sqrt(pow(JWSC_2_PI, D) * sigma_det);
00134 
00135     subtract_vectors_f(&v_1, x, mu);
00136     multiply_matrix_and_vector_f(&v_2, sigma_inv, v_1);
00137     calc_vector_dot_prod_f(&d, v_1, v_2);
00138 
00139     *p_out = (float)(exp(-0.5 * d) / c);
00140 
00141     free_vector_i32(pivot);
00142     free_matrix_f(sigma_lu);
00143     free_matrix_f(sigma_inv);
00144     free_vector_f(v_1);
00145     free_vector_f(v_2);
00146 
00147     return NULL;
00148 }
00149 
00160 Error* mv_gaussian_pdf_d
00161 (
00162     double*         p_out,
00163     const Vector_d* mu, 
00164     const Matrix_d* sigma, 
00165     const Vector_d* x
00166 )
00167 {
00168     uint32_t    D;
00169     double      sigma_det;
00170     double      c, d;
00171     Matrix_d*   sigma_lu = NULL;
00172     Matrix_d*   sigma_inv = NULL;
00173     Vector_i32* pivot = NULL;
00174     Vector_d*   v_1 = NULL;
00175     Vector_d*   v_2 = NULL;
00176     Error*      e;
00177 
00178     D = mu->num_elts;
00179 
00180     if (D != sigma->num_rows || D != sigma->num_cols || D != x->num_elts)
00181     {
00182         return JWSC_EARG("Invalid argument dimensions");
00183     }
00184 
00185     if ((e = lu_decompose_matrix_d(&sigma_lu, &pivot, sigma)) != NULL)
00186     {
00187         free_error(e);
00188         return JWSC_EARG("Covariance matrix is singular");
00189     }
00190 
00191     calc_lu_matrix_determinant_d(&sigma_det, sigma_lu, pivot);
00192 
00193     if (sigma_det < 1.0e-64)
00194     {
00195         fprintf(stderr, "%e\n", sigma_det);
00196         free_vector_i32(pivot);
00197         free_matrix_d(sigma_lu);
00198         return JWSC_EARG("Invalid covariance matrix");
00199     }
00200 
00201     if ((e = invert_lu_matrix_d(&sigma_inv, sigma_lu, pivot)) != NULL)
00202     {
00203         free_error(e);
00204         free_vector_i32(pivot);
00205         free_matrix_d(sigma_lu);
00206         return JWSC_EARG("Covariance matrix is singular");
00207     }
00208 
00209     c = sqrt(pow(JWSC_2_PI, D) * sigma_det);
00210 
00211     subtract_vectors_d(&v_1, x, mu);
00212     multiply_matrix_and_vector_d(&v_2, sigma_inv, v_1);
00213     calc_vector_dot_prod_d(&d, v_1, v_2);
00214 
00215     *p_out = exp(-0.5 * d) / c;
00216 
00217     free_vector_i32(pivot);
00218     free_matrix_d(sigma_lu);
00219     free_matrix_d(sigma_inv);
00220     free_vector_d(v_1);
00221     free_vector_d(v_2);
00222 
00223     return NULL;
00224 }
00225 
00227 #endif
00228 
00229 
00230 #if defined JWSC_HAVE_LAPACK
00231 
00248 Error* set_mv_gaussian_pdf_f
00249 (
00250     Vector_f**      p_out,
00251     const Vector_f* mu, 
00252     const Matrix_f* sigma, 
00253     const Matrix_f* x
00254 )
00255 {
00256     uint32_t    D;
00257     uint32_t    n, N;
00258     float       sigma_det;
00259     double      c;
00260     float       d;
00261     Matrix_f*   sigma_lu = NULL;
00262     Matrix_f*   sigma_inv = NULL;
00263     Vector_i32* pivot = NULL;
00264     Vector_f*   v_1 = NULL;
00265     Vector_f*   v_2 = NULL;
00266     Vector_f*   x_n = NULL;
00267     Vector_f*   p;
00268     Error*      e;
00269 
00270     D = x->num_cols;
00271     N = x->num_rows;
00272 
00273     if (D != sigma->num_rows || D != sigma->num_cols || D != mu->num_elts)
00274     {
00275         return JWSC_EARG("Invalid argument dimensions");
00276     }
00277 
00278     if ((e = lu_decompose_matrix_f(&sigma_lu, &pivot, sigma)) != NULL)
00279     {
00280         free_error(e);
00281         return JWSC_EARG("Covariance matrix is singular");
00282     }
00283 
00284     calc_lu_matrix_determinant_f(&sigma_det, sigma_lu, pivot);
00285 
00286     if (sigma_det < 1.0e-64)
00287     {
00288         fprintf(stderr, "%e\n", sigma_det);
00289         free_vector_i32(pivot);
00290         free_matrix_f(sigma_lu);
00291         return JWSC_EARG("Invalid covariance matrix");
00292     }
00293 
00294     if ((e = invert_lu_matrix_f(&sigma_inv, sigma_lu, pivot)) != NULL)
00295     {
00296         free_error(e);
00297         free_vector_i32(pivot);
00298         free_matrix_f(sigma_lu);
00299         return JWSC_EARG("Covariance matrix is singular");
00300     }
00301 
00302     create_vector_f(p_out, N);
00303     p = *p_out;
00304 
00305     c = sqrt(pow(JWSC_2_PI, D) * sigma_det);
00306 
00307     for (n = 0; n < N; n++)
00308     {
00309         copy_vector_from_matrix_f(&x_n, x, MATRIX_ROW_VECTOR, n);
00310         subtract_vectors_f(&v_1, x_n, mu);
00311         multiply_matrix_and_vector_f(&v_2, sigma_inv, v_1);
00312         calc_vector_dot_prod_f(&d, v_1, v_2);
00313 
00314         p->elts[ n ] = exp(-0.5 * d) / c;
00315     }
00316 
00317     free_vector_i32(pivot);
00318     free_matrix_f(sigma_lu);
00319     free_matrix_f(sigma_inv);
00320     free_vector_f(v_1);
00321     free_vector_f(v_2);
00322     free_vector_f(x_n);
00323 
00324     return NULL;
00325 }
00326 
00337 Error* set_mv_gaussian_pdf_d
00338 (
00339     Vector_d**      p_out,
00340     const Vector_d* mu, 
00341     const Matrix_d* sigma, 
00342     const Matrix_d* x
00343 )
00344 {
00345     uint32_t    D;
00346     uint32_t    n, N;
00347     double      sigma_det;
00348     double      c, d;
00349     Matrix_d*   sigma_lu = NULL;
00350     Matrix_d*   sigma_inv = NULL;
00351     Vector_i32* pivot = NULL;
00352     Vector_d*   v_1 = NULL;
00353     Vector_d*   v_2 = NULL;
00354     Vector_d*   x_n = NULL;
00355     Vector_d*   p;
00356     Error*      e;
00357 
00358     D = x->num_cols;
00359     N = x->num_rows;
00360 
00361     if (D != sigma->num_rows || D != sigma->num_cols || D != mu->num_elts)
00362     {
00363         return JWSC_EARG("Invalid argument dimensions");
00364     }
00365 
00366     if ((e = lu_decompose_matrix_d(&sigma_lu, &pivot, sigma)) != NULL)
00367     {
00368         free_error(e);
00369         return JWSC_EARG("Covariance matrix is singular");
00370     }
00371 
00372     calc_lu_matrix_determinant_d(&sigma_det, sigma_lu, pivot);
00373 
00374     if (sigma_det < 1.0e-64)
00375     {
00376         fprintf(stderr, "%e\n", sigma_det);
00377         free_vector_i32(pivot);
00378         free_matrix_d(sigma_lu);
00379         return JWSC_EARG("Invalid covariance matrix");
00380     }
00381 
00382     if ((e = invert_lu_matrix_d(&sigma_inv, sigma_lu, pivot)) != NULL)
00383     {
00384         free_error(e);
00385         free_vector_i32(pivot);
00386         free_matrix_d(sigma_lu);
00387         return JWSC_EARG("Covariance matrix is singular");
00388     }
00389 
00390     create_vector_d(p_out, N);
00391     p = *p_out;
00392 
00393     c = sqrt(pow(JWSC_2_PI, D) * sigma_det);
00394 
00395     for (n = 0; n < N; n++)
00396     {
00397         copy_vector_from_matrix_d(&x_n, x, MATRIX_ROW_VECTOR, n);
00398         subtract_vectors_d(&v_1, x_n, mu);
00399         multiply_matrix_and_vector_d(&v_2, sigma_inv, v_1);
00400         calc_vector_dot_prod_d(&d, v_1, v_2);
00401 
00402         p->elts[ n ] = exp(-0.5 * d) / c;
00403     }
00404 
00405     free_vector_i32(pivot);
00406     free_matrix_d(sigma_lu);
00407     free_matrix_d(sigma_inv);
00408     free_vector_d(v_1);
00409     free_vector_d(v_2);
00410     free_vector_d(x_n);
00411 
00412     return NULL;
00413 }
00414 
00416 #endif
00417 
00418 
00419 #if defined JWSC_HAVE_LAPACK
00420 
00437 Error* log_mv_gaussian_pdf_f
00438 (
00439     float*          p_out,
00440     const Vector_f* mu, 
00441     const Matrix_f* sigma, 
00442     const Vector_f* x
00443 )
00444 {
00445     uint32_t    D;
00446     float       sigma_det;
00447     float       d;
00448     double      c;
00449     Matrix_f*   sigma_lu = NULL;
00450     Matrix_f*   sigma_inv = NULL;
00451     Vector_i32* pivot = NULL;
00452     Vector_f*   v_1 = NULL;
00453     Vector_f*   v_2 = NULL;
00454     Error*      e;
00455 
00456     D = mu->num_elts;
00457 
00458     if (D != sigma->num_rows || D != sigma->num_cols || D != x->num_elts)
00459     {
00460         return JWSC_EARG("Invalid argument dimensions");
00461     }
00462 
00463     if ((e = lu_decompose_matrix_f(&sigma_lu, &pivot, sigma)) != NULL)
00464     {
00465         free_error(e);
00466         return JWSC_EARG("Covariance matrix is singular");
00467     }
00468 
00469     calc_lu_matrix_determinant_f(&sigma_det, sigma_lu, pivot);
00470 
00471     if (sigma_det < 1.0e-10f)
00472     {
00473         fprintf(stderr, "%e\n", sigma_det);
00474         free_vector_i32(pivot);
00475         free_matrix_f(sigma_lu);
00476         return JWSC_EARG("Invalid covariance matrix");
00477     }
00478 
00479     if ((e = invert_lu_matrix_f(&sigma_inv, sigma_lu, pivot)) != NULL)
00480     {
00481         free_error(e);
00482         free_vector_i32(pivot);
00483         free_matrix_f(sigma_lu);
00484         return JWSC_EARG("Covariance matrix is singular");
00485     }
00486 
00487     c = sqrt(pow(JWSC_2_PI, D) * sigma_det);
00488 
00489     subtract_vectors_f(&v_1, x, mu);
00490     multiply_matrix_and_vector_f(&v_2, sigma_inv, v_1);
00491     calc_vector_dot_prod_f(&d, v_1, v_2);
00492 
00493     *p_out = (float)(-0.5 * d - log(c));
00494 
00495     free_vector_i32(pivot);
00496     free_matrix_f(sigma_lu);
00497     free_matrix_f(sigma_inv);
00498     free_vector_f(v_1);
00499     free_vector_f(v_2);
00500 
00501     return NULL;
00502 }
00503 
00514 Error* log_mv_gaussian_pdf_d
00515 (
00516     double*         p_out,
00517     const Vector_d* mu, 
00518     const Matrix_d* sigma, 
00519     const Vector_d* x
00520 )
00521 {
00522     uint32_t    D;
00523     double      sigma_det;
00524     double      c, d;
00525     Matrix_d*   sigma_lu = NULL;
00526     Matrix_d*   sigma_inv = NULL;
00527     Vector_i32* pivot = NULL;
00528     Vector_d*   v_1 = NULL;
00529     Vector_d*   v_2 = NULL;
00530     Error*      e;
00531 
00532     D = mu->num_elts;
00533 
00534     if (D != sigma->num_rows || D != sigma->num_cols || D != x->num_elts)
00535     {
00536         return JWSC_EARG("Invalid argument dimensions");
00537     }
00538 
00539     if ((e = lu_decompose_matrix_d(&sigma_lu, &pivot, sigma)) != NULL)
00540     {
00541         free_error(e);
00542         return JWSC_EARG("Covariance matrix is singular");
00543     }
00544 
00545     calc_lu_matrix_determinant_d(&sigma_det, sigma_lu, pivot);
00546 
00547     if (sigma_det < 1.0e-64)
00548     {
00549         fprintf(stderr, "%e\n", sigma_det);
00550         free_vector_i32(pivot);
00551         free_matrix_d(sigma_lu);
00552         return JWSC_EARG("Invalid covariance matrix");
00553     }
00554 
00555     if ((e = invert_lu_matrix_d(&sigma_inv, sigma_lu, pivot)) != NULL)
00556     {
00557         free_error(e);
00558         free_vector_i32(pivot);
00559         free_matrix_d(sigma_lu);
00560         return JWSC_EARG("Covariance matrix is singular");
00561     }
00562 
00563     c = sqrt(pow(JWSC_2_PI, D) * sigma_det);
00564 
00565     subtract_vectors_d(&v_1, x, mu);
00566     multiply_matrix_and_vector_d(&v_2, sigma_inv, v_1);
00567     calc_vector_dot_prod_d(&d, v_1, v_2);
00568 
00569     *p_out = -0.5 * d - log(c);
00570 
00571     free_vector_i32(pivot);
00572     free_matrix_d(sigma_lu);
00573     free_matrix_d(sigma_inv);
00574     free_vector_d(v_1);
00575     free_vector_d(v_2);
00576 
00577     return NULL;
00578 }
00579 
00581 #endif
00582 
00583 
00601 void sample_standard_mv_gaussian_pdf_f
00602 (
00603     Vector_f** x_out, 
00604     uint32_t   D
00605 )
00606 {
00607     uint32_t  d;
00608     uint8_t   accept;
00609     float     s, l, u;
00610     Vector_f* x;
00611 
00612     create_vector_f(x_out, D);
00613     x = *x_out;
00614 
00615     for (d = 0; d < D; d++)
00616     {
00617         accept = 0;
00618 
00619         while (!accept)
00620         {
00621             s = sample_uniform_pdf_f(-6.0, 6.0);
00622             l = standard_gaussian_pdf_f(s);
00623             u = sample_uniform_pdf_f(0, 1);
00624 
00625             if (u <= l)
00626             {
00627                 accept = 1;
00628             }
00629         }
00630 
00631         x->elts[ d ] = s;
00632     }
00633 }
00634 
00645 void sample_standard_mv_gaussian_pdf_d
00646 (
00647     Vector_d** x_out, 
00648     uint32_t   D
00649 )
00650 {
00651     uint32_t  d;
00652     uint8_t   accept;
00653     double    s, l, u;
00654     Vector_d* x;
00655 
00656     create_vector_d(x_out, D);
00657     x = *x_out;
00658 
00659     for (d = 0; d < D; d++)
00660     {
00661         accept = 0;
00662 
00663         while (!accept)
00664         {
00665             s = sample_uniform_pdf_d(-6.0, 6.0);
00666             l = standard_gaussian_pdf_d(s);
00667             u = sample_uniform_pdf_d(0, 1);
00668 
00669             if (u <= l)
00670             {
00671                 accept = 1;
00672             }
00673         }
00674 
00675         x->elts[ d ] = s;
00676     }
00677 }
00678 
00700 void set_sample_standard_mv_gaussian_pdf_f
00701 (
00702     Matrix_f** x_out, 
00703     uint32_t   N,
00704     uint32_t   D
00705 )
00706 {
00707     uint32_t  n, d;
00708     uint8_t   accept;
00709     float     s, l, u;
00710     Matrix_f* x;
00711 
00712     create_matrix_f(x_out, N, D);
00713     x = *x_out;
00714 
00715     for (n = 0; n < N; n++)
00716     {
00717         for (d = 0; d < D; d++)
00718         {
00719             accept = 0;
00720 
00721             while (!accept)
00722             {
00723                 s = sample_uniform_pdf_f(-6.0f, 6.0f);
00724                 l = standard_gaussian_pdf_f(s);
00725                 u = sample_uniform_pdf_f(0, 1);
00726 
00727                 if (u <= l)
00728                 {
00729                     accept = 1;
00730                 }
00731             }
00732 
00733             x->elts[ n ][ d ] = s;
00734         }
00735     }
00736 }
00737 
00749 void set_sample_standard_mv_gaussian_pdf_d
00750 (
00751     Matrix_d** x_out, 
00752     uint32_t   N,
00753     uint32_t   D
00754 )
00755 {
00756     uint32_t  n, d;
00757     uint8_t   accept;
00758     double    s, l, u;
00759     Matrix_d* x;
00760 
00761     create_matrix_d(x_out, N, D);
00762     x = *x_out;
00763 
00764     for (n = 0; n < N; n++)
00765     {
00766         for (d = 0; d < D; d++)
00767         {
00768             accept = 0;
00769 
00770             while (!accept)
00771             {
00772                 s = sample_uniform_pdf_d(-6.0, 6.0);
00773                 l = standard_gaussian_pdf_d(s);
00774                 u = sample_uniform_pdf_d(0, 1);
00775 
00776                 if (u <= l)
00777                 {
00778                     accept = 1;
00779                 }
00780             }
00781 
00782             x->elts[ n ][ d ] = s;
00783         }
00784     }
00785 }
00786 
00790 #if defined JWSC_HAVE_LAPACK
00791 
00809 Error* sample_mv_gaussian_pdf_f
00810 (
00811     Vector_f**      x_out,
00812     const Vector_f* mu, 
00813     const Matrix_f* sigma
00814 )
00815 {
00816     uint32_t  D, d;
00817     Vector_f* x;
00818     Matrix_f* eigvec = NULL;
00819     Vector_f* eigval = NULL;
00820     Error*    err;
00821 
00822     D = mu->num_elts;
00823 
00824     sample_standard_mv_gaussian_pdf_f(x_out, D);
00825     x = *x_out;
00826 
00827     if ((err = solve_real_symmetric_matrix_eigenproblem_f(&eigvec, &eigval, 
00828                     sigma)))
00829     {
00830         free_vector_f(*x_out); *x_out = NULL;
00831         return err;
00832     }
00833 
00834     for (d = 0; d < D; d++)
00835     {
00836         if (eigval->elts[ d ] < 0)
00837         {
00838             free_vector_f(*x_out); *x_out = NULL;
00839             free_matrix_f(eigvec);
00840             free_vector_f(eigval);
00841             return JWSC_EARG("Covariance matrix not positive semi-definite");
00842         }
00843 
00844         x->elts[ d ] *= sqrt(eigval->elts[ d ]);
00845     }
00846 
00847     assert(multiply_matrix_and_vector_f(&x, eigvec, x) == NULL);
00848     assert(add_vectors_f(&x, mu, x) == NULL);
00849 
00850     free_matrix_f(eigvec);
00851     free_vector_f(eigval);
00852 
00853     return NULL;
00854 }
00855 
00867 Error* sample_mv_gaussian_pdf_d
00868 (
00869     Vector_d**      x_out,
00870     const Vector_d* mu, 
00871     const Matrix_d* sigma
00872 )
00873 {
00874     uint32_t  D, d;
00875     Vector_d* x;
00876     Matrix_d* eigvec = NULL;
00877     Vector_d* eigval = NULL;
00878     Error*    err;
00879 
00880     D = mu->num_elts;
00881 
00882     sample_standard_mv_gaussian_pdf_d(x_out, D);
00883     x = *x_out;
00884 
00885     if ((err = solve_real_symmetric_matrix_eigenproblem_d(&eigvec, &eigval, 
00886                     sigma)))
00887     {
00888         free_vector_d(*x_out); *x_out = NULL;
00889         return err;
00890     }
00891 
00892     for (d = 0; d < D; d++)
00893     {
00894         if (eigval->elts[ d ] < -1.0e-16)
00895         {
00896             free_vector_d(*x_out); *x_out = NULL;
00897             free_matrix_d(eigvec);
00898             free_vector_d(eigval);
00899             return JWSC_EARG("Covariance matrix not positive semi-definite");
00900         }
00901         else if (eigval->elts[ d ] < 0)
00902         {
00903             eigval->elts[ d ] = 0;
00904         }
00905         else
00906         {
00907             x->elts[ d ] *= sqrt(eigval->elts[ d ]);
00908         }
00909     }
00910 
00911     assert(multiply_matrix_and_vector_d(&x, eigvec, x) == NULL);
00912     assert(add_vectors_d(&x, mu, x) == NULL);
00913 
00914     free_matrix_d(eigvec);
00915     free_vector_d(eigval);
00916 
00917     return NULL;
00918 }
00919 
00921 #endif
00922 
00923 
00924 #if defined JWSC_HAVE_LAPACK
00925 
00944 Error* set_sample_mv_gaussian_pdf_f
00945 (
00946     Matrix_f**      x_out,
00947     uint32_t        N,
00948     const Vector_f* mu, 
00949     const Matrix_f* sigma
00950 )
00951 {
00952     uint32_t  D, d;
00953     uint32_t  n;
00954     Matrix_f* x;
00955     Matrix_f* eigvec = NULL;
00956     Vector_f* eigval = NULL;
00957     Error*    err;
00958 
00959     D = mu->num_elts;
00960 
00961     set_sample_standard_mv_gaussian_pdf_f(x_out, N, D);
00962     x = *x_out;
00963 
00964     if ((err = solve_real_symmetric_matrix_eigenproblem_f(&eigvec, &eigval, 
00965                     sigma)))
00966     {
00967         free_matrix_f(*x_out); *x_out = NULL;
00968         return err;
00969     }
00970 
00971     for (d = 0; d < D; d++)
00972     {
00973         if (eigval->elts[ d ] < 0)
00974         {
00975             free_matrix_f(*x_out); *x_out = NULL;
00976             free_matrix_f(eigvec);
00977             free_vector_f(eigval);
00978             return JWSC_EARG("Covariance matrix not positive semi-definite");
00979         }
00980     }
00981 
00982     for (n = 0; n < N; n++)
00983     {
00984         for (d = 0; d < D; d++)
00985         {
00986             x->elts[ n ][ d ] *= sqrt(eigval->elts[ d ]);
00987         }
00988     }
00989 
00990     transpose_matrix_f(&eigvec, eigvec);
00991     assert(multiply_matrices_f(&x, x, eigvec) == NULL);
00992 
00993     for (n = 0; n < N; n++)
00994     {
00995         for (d = 0; d < D; d++)
00996         {
00997             x->elts[ n ][ d ] += mu->elts[ d ];
00998         }
00999     }
01000 
01001     free_matrix_f(eigvec);
01002     free_vector_f(eigval);
01003 
01004     return NULL;
01005 }
01006 
01019 Error* set_sample_mv_gaussian_pdf_d
01020 (
01021     Matrix_d**      x_out,
01022     uint32_t        N,
01023     const Vector_d* mu, 
01024     const Matrix_d* sigma
01025 )
01026 {
01027     uint32_t  D, d;
01028     uint32_t  n;
01029     Matrix_d* x;
01030     Matrix_d* eigvec = NULL;
01031     Vector_d* eigval = NULL;
01032     Error*    err;
01033 
01034     D = mu->num_elts;
01035 
01036     set_sample_standard_mv_gaussian_pdf_d(x_out, N, D);
01037     x = *x_out;
01038 
01039     if ((err = solve_real_symmetric_matrix_eigenproblem_d(&eigvec, &eigval, 
01040                     sigma)))
01041     {
01042         free_matrix_d(*x_out); *x_out = NULL;
01043         return err;
01044     }
01045 
01046     for (d = 0; d < D; d++)
01047     {
01048         if (eigval->elts[ d ] < 0)
01049         {
01050             free_matrix_d(*x_out); *x_out = NULL;
01051             free_matrix_d(eigvec);
01052             free_vector_d(eigval);
01053             return JWSC_EARG("Covariance matrix not positive semi-definite");
01054         }
01055     }
01056 
01057     for (n = 0; n < N; n++)
01058     {
01059         for (d = 0; d < D; d++)
01060         {
01061             x->elts[ n ][ d ] *= sqrt(eigval->elts[ d ]);
01062         }
01063     }
01064 
01065     transpose_matrix_d(&eigvec, eigvec);
01066     assert(multiply_matrices_d(&x, x, eigvec) == NULL);
01067 
01068     for (n = 0; n < N; n++)
01069     {
01070         for (d = 0; d < D; d++)
01071         {
01072             x->elts[ n ][ d ] += mu->elts[ d ];
01073         }
01074     }
01075 
01076     free_matrix_d(eigvec);
01077     free_vector_d(eigval);
01078 
01079     return NULL;
01080 }
01081 
01083 #endif