JWS C Library
C language utility library
|
00001 /* 00002 * This work is licensed under a Creative Commons 00003 * Attribution-Noncommercial-Share Alike 3.0 United States License. 00004 * 00005 * http://creativecommons.org/licenses/by-nc-sa/3.0/us/ 00006 * 00007 * You are free: 00008 * 00009 * to Share - to copy, distribute, display, and perform the work 00010 * to Remix - to make derivative works 00011 * 00012 * Under the following conditions: 00013 * 00014 * Attribution. You must attribute the work in the manner specified by the 00015 * author or licensor (but not in any way that suggests that they endorse you 00016 * or your use of the work). 00017 * 00018 * Noncommercial. You may not use this work for commercial purposes. 00019 * 00020 * Share Alike. If you alter, transform, or build upon this work, you may 00021 * distribute the resulting work only under the same or similar license to 00022 * this one. 00023 * 00024 * For any reuse or distribution, you must make clear to others the license 00025 * terms of this work. The best way to do this is by including this header. 00026 * 00027 * Any of the above conditions can be waived if you get permission from the 00028 * copyright holder. 00029 * 00030 * Apart from the remix rights granted under this license, nothing in this 00031 * license impairs or restricts the author's moral rights. 00032 */ 00033 00034 00049 #include <jwsc/config.h> 00050 00051 #include <stdlib.h> 00052 #include <math.h> 00053 #include <assert.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/vector/vector.h" 00060 #include "jwsc/vector/vector_math.h" 00061 00062 00078 void add_scalar_to_vector_f(Vector_f** v_out, const Vector_f* v_in, float a) 00079 { 00080 uint32_t num_elts; 00081 uint32_t elt; 00082 Vector_f* v; 00083 00084 num_elts = v_in->num_elts; 00085 00086 if (*v_out != v_in) 00087 { 00088 create_vector_f(v_out, num_elts); 00089 } 00090 v = *v_out; 00091 00092 for (elt = 0; elt < num_elts; elt++) 00093 { 00094 v->elts[ elt ] = a + v_in->elts[ elt ]; 00095 } 00096 } 00097 00106 void add_scalar_to_vector_d(Vector_d** v_out, const Vector_d* v_in, double a) 00107 { 00108 uint32_t num_elts; 00109 uint32_t elt; 00110 Vector_d* v; 00111 00112 num_elts = v_in->num_elts; 00113 00114 if (*v_out != v_in) 00115 { 00116 create_vector_d(v_out, num_elts); 00117 } 00118 v = *v_out; 00119 00120 for (elt = 0; elt < num_elts; elt++) 00121 { 00122 v->elts[ elt ] = a + v_in->elts[ elt ]; 00123 } 00124 } 00125 00134 void add_scalar_to_vector_cf 00135 ( 00136 Vector_cf** v_out, 00137 const Vector_cf* v_in, 00138 Complex_f z 00139 ) 00140 { 00141 uint32_t num_elts; 00142 uint32_t elt; 00143 Vector_cf* v; 00144 00145 num_elts = v_in->num_elts; 00146 00147 if (*v_out != v_in) 00148 { 00149 create_vector_cf(v_out, num_elts); 00150 } 00151 v = *v_out; 00152 00153 for (elt = 0; elt < num_elts; elt++) 00154 { 00155 v->elts[ elt ].r = z.r + v_in->elts[ elt ].r; 00156 v->elts[ elt ].i = z.i + v_in->elts[ elt ].i; 00157 } 00158 } 00159 00168 void add_scalar_to_vector_cd 00169 ( 00170 Vector_cd** v_out, 00171 const Vector_cd* v_in, 00172 Complex_d z 00173 ) 00174 { 00175 uint32_t num_elts; 00176 uint32_t elt; 00177 Vector_cd* v; 00178 00179 num_elts = v_in->num_elts; 00180 00181 if (*v_out != v_in) 00182 { 00183 create_vector_cd(v_out, num_elts); 00184 } 00185 v = *v_out; 00186 00187 for (elt = 0; elt < num_elts; elt++) 00188 { 00189 v->elts[ elt ].r = z.r + v_in->elts[ elt ].r; 00190 v->elts[ elt ].i = z.i + v_in->elts[ elt ].i; 00191 } 00192 } 00193 00214 void multiply_vector_by_scalar_f 00215 ( 00216 Vector_f** v_out, 00217 const Vector_f* v_in, 00218 float a 00219 ) 00220 { 00221 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00222 uint32_t num_elts; 00223 Vector_f* v; 00224 00225 num_elts = v_in->num_elts; 00226 00227 if (*v_out != v_in) 00228 { 00229 copy_vector_f(v_out, v_in); 00230 } 00231 v = *v_out; 00232 00233 blas_sscal(num_elts, a, v->elts, 1); 00234 #else 00235 uint32_t num_elts; 00236 uint32_t elt; 00237 Vector_f* v; 00238 00239 num_elts = v_in->num_elts; 00240 00241 if (*v_out != v_in) 00242 { 00243 create_vector_f(v_out, num_elts); 00244 } 00245 v = *v_out; 00246 00247 for (elt = 0; elt < num_elts; elt++) 00248 { 00249 v->elts[ elt ] = a * v_in->elts[ elt ]; 00250 } 00251 #endif 00252 } 00253 00262 void multiply_vector_by_scalar_d 00263 ( 00264 Vector_d** v_out, 00265 const Vector_d* v_in, 00266 double a 00267 ) 00268 { 00269 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00270 uint32_t num_elts; 00271 Vector_d* v; 00272 00273 num_elts = v_in->num_elts; 00274 00275 if (*v_out != v_in) 00276 { 00277 copy_vector_d(v_out, v_in); 00278 } 00279 v = *v_out; 00280 00281 blas_dscal(num_elts, a, v->elts, 1); 00282 #else 00283 uint32_t num_elts; 00284 uint32_t elt; 00285 Vector_d* v; 00286 00287 num_elts = v_in->num_elts; 00288 00289 if (*v_out != v_in) 00290 { 00291 create_vector_d(v_out, num_elts); 00292 } 00293 v = *v_out; 00294 00295 for (elt = 0; elt < num_elts; elt++) 00296 { 00297 v->elts[ elt ] = a * v_in->elts[ elt ]; 00298 } 00299 #endif 00300 } 00301 00310 void multiply_vector_by_scalar_cf 00311 ( 00312 Vector_cf** v_out, 00313 const Vector_cf* v_in, 00314 Complex_f z 00315 ) 00316 { 00317 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00318 uint32_t num_elts; 00319 Vector_cf* v; 00320 00321 num_elts = v_in->num_elts; 00322 00323 if (*v_out != v_in) 00324 { 00325 copy_vector_cf(v_out, v_in); 00326 } 00327 v = *v_out; 00328 00329 blas_cscal(num_elts, z, v->elts, 1); 00330 #else 00331 uint32_t num_elts; 00332 uint32_t elt; 00333 float r, i; 00334 Vector_cf* v; 00335 00336 num_elts = v_in->num_elts; 00337 00338 if (*v_out != v_in) 00339 { 00340 create_vector_cf(v_out, num_elts); 00341 } 00342 v = *v_out; 00343 00344 for (elt = 0; elt < num_elts; elt++) 00345 { 00346 r = z.r*v_in->elts[ elt ].r - z.i*v_in->elts[ elt ].i; 00347 i = z.i*v_in->elts[ elt ].r + z.r*v_in->elts[ elt ].i; 00348 00349 v->elts[ elt ].r = r; 00350 v->elts[ elt ].i = i; 00351 } 00352 #endif 00353 } 00354 00363 void multiply_vector_by_scalar_cd 00364 ( 00365 Vector_cd** v_out, 00366 const Vector_cd* v_in, 00367 Complex_d z 00368 ) 00369 { 00370 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00371 uint32_t num_elts; 00372 Vector_cd* v; 00373 00374 num_elts = v_in->num_elts; 00375 00376 if (*v_out != v_in) 00377 { 00378 copy_vector_cd(v_out, v_in); 00379 } 00380 v = *v_out; 00381 00382 blas_zscal(num_elts, z, v->elts, 1); 00383 #else 00384 uint32_t num_elts; 00385 uint32_t elt; 00386 double r, i; 00387 Vector_cd* v; 00388 00389 num_elts = v_in->num_elts; 00390 00391 if (*v_out != v_in) 00392 { 00393 create_vector_cd(v_out, num_elts); 00394 } 00395 v = *v_out; 00396 00397 for (elt = 0; elt < num_elts; elt++) 00398 { 00399 r = z.r*v_in->elts[ elt ].r - z.i*v_in->elts[ elt ].i; 00400 i = z.i*v_in->elts[ elt ].r + z.r*v_in->elts[ elt ].i; 00401 00402 v->elts[ elt ].r = r; 00403 v->elts[ elt ].i = i; 00404 } 00405 #endif 00406 } 00407 00431 Error* calc_vector_dot_prod_f 00432 ( 00433 float* dp_out, 00434 const Vector_f* v_1, 00435 const Vector_f* v_2 00436 ) 00437 { 00438 uint32_t num_elts; 00439 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00440 #else 00441 uint32_t elt; 00442 #endif 00443 00444 num_elts = v_1->num_elts; 00445 if (num_elts != v_2->num_elts) 00446 { 00447 return JWSC_EARG("Dot product requires vectors with equal dimensions"); 00448 } 00449 00450 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00451 *dp_out = blas_sdot(num_elts, v_1->elts, 1, v_2->elts, 1); 00452 #else 00453 *dp_out = 0; 00454 for (elt = 0; elt < num_elts; elt++) 00455 { 00456 *dp_out += v_1->elts[ elt ] * v_2->elts[ elt ]; 00457 } 00458 #endif 00459 00460 return NULL; 00461 } 00462 00474 Error* calc_vector_dot_prod_d 00475 ( 00476 double* dp_out, 00477 const Vector_d* v_1, 00478 const Vector_d* v_2 00479 ) 00480 { 00481 uint32_t num_elts; 00482 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00483 #else 00484 uint32_t elt; 00485 #endif 00486 00487 num_elts = v_1->num_elts; 00488 if (num_elts != v_2->num_elts) 00489 { 00490 return JWSC_EARG("Dot product requires vectors with equal dimensions"); 00491 } 00492 00493 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00494 *dp_out = blas_ddot(num_elts, v_1->elts, 1, v_2->elts, 1); 00495 #else 00496 *dp_out = 0; 00497 for (elt = 0; elt < num_elts; elt++) 00498 { 00499 *dp_out += v_1->elts[ elt ] * v_2->elts[ elt ]; 00500 } 00501 #endif 00502 00503 return NULL; 00504 } 00505 00533 Error* calc_3d_vector_cross_prod_f 00534 ( 00535 Vector_f** v_out, 00536 const Vector_f* v_1, 00537 const Vector_f* v_2 00538 ) 00539 { 00540 float cp_1, cp_2, cp_3; 00541 00542 if (v_1->num_elts != 3 || v_2->num_elts != 3) 00543 { 00544 if (*v_out != v_1 && *v_out != v_2) 00545 { 00546 free_vector_f(*v_out); *v_out = NULL; 00547 } 00548 return JWSC_EARG("Cross product requires vectors with three-dimensions"); 00549 } 00550 00551 cp_1 = v_1->elts[1] * v_2->elts[2]; 00552 cp_1 -= v_1->elts[2] * v_2->elts[1]; 00553 cp_2 = v_1->elts[2] * v_2->elts[0]; 00554 cp_2 -= v_1->elts[0] * v_2->elts[2]; 00555 cp_3 = v_1->elts[0] * v_2->elts[1]; 00556 cp_3 -= v_1->elts[1] * v_2->elts[0]; 00557 00558 create_vector_f(v_out, 3); 00559 (*v_out)->elts[0] = cp_1; 00560 (*v_out)->elts[1] = cp_2; 00561 (*v_out)->elts[2] = cp_3; 00562 00563 return NULL; 00564 } 00565 00581 Error* calc_3d_vector_cross_prod_d 00582 ( 00583 Vector_d** v_out, 00584 const Vector_d* v_1, 00585 const Vector_d* v_2 00586 ) 00587 { 00588 double cp_1, cp_2, cp_3; 00589 00590 if (v_1->num_elts != 3 || v_2->num_elts != 3) 00591 { 00592 if (*v_out != v_1 && *v_out != v_2) 00593 { 00594 free_vector_d(*v_out); *v_out = NULL; 00595 } 00596 return JWSC_EARG("Cross product requires vectors with three-dimensions"); 00597 } 00598 00599 cp_1 = v_1->elts[1] * v_2->elts[2]; 00600 cp_1 -= v_1->elts[2] * v_2->elts[1]; 00601 cp_2 = v_1->elts[2] * v_2->elts[0]; 00602 cp_2 -= v_1->elts[0] * v_2->elts[2]; 00603 cp_3 = v_1->elts[0] * v_2->elts[1]; 00604 cp_3 -= v_1->elts[1] * v_2->elts[0]; 00605 00606 create_vector_d(v_out, 3); 00607 (*v_out)->elts[0] = cp_1; 00608 (*v_out)->elts[1] = cp_2; 00609 (*v_out)->elts[2] = cp_3; 00610 00611 return NULL; 00612 } 00613 00630 void calc_vector_asum_f(float* sum_out, const Vector_f* v) 00631 { 00632 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00633 *sum_out = blas_sasum(v->num_elts, v->elts, 1); 00634 #else 00635 uint32_t num_elts; 00636 uint32_t elt; 00637 00638 num_elts = v->num_elts; 00639 *sum_out = 0; 00640 00641 for (elt = 0; elt < num_elts; elt++) 00642 { 00643 (*sum_out) += (float)fabs(v->elts[ elt ]); 00644 } 00645 #endif 00646 } 00647 00652 void calc_vector_asum_d(double* sum_out, const Vector_d* v) 00653 { 00654 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00655 *sum_out = blas_dasum(v->num_elts, v->elts, 1); 00656 #else 00657 uint32_t num_elts; 00658 uint32_t elt; 00659 00660 num_elts = v->num_elts; 00661 *sum_out = 0; 00662 00663 for (elt = 0; elt < num_elts; elt++) 00664 { 00665 (*sum_out) += fabs(v->elts[ elt ]); 00666 } 00667 #endif 00668 } 00669 00686 void calc_vector_mag_f(float* mag_out, const Vector_f* v) 00687 { 00688 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00689 *mag_out = blas_snrm2(v->num_elts, v->elts, 1); 00690 #else 00691 uint32_t num_elts; 00692 uint32_t elt; 00693 00694 num_elts = v->num_elts; 00695 *mag_out = 0; 00696 00697 for (elt = 0; elt < num_elts; elt++) 00698 { 00699 *mag_out += v->elts[ elt ] * v->elts[ elt ]; 00700 } 00701 00702 *mag_out = (float)sqrt(*mag_out); 00703 #endif 00704 } 00705 00710 void calc_vector_mag_d(double* mag_out, const Vector_d* v) 00711 { 00712 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00713 *mag_out = blas_dnrm2(v->num_elts, v->elts, 1); 00714 #else 00715 uint32_t num_elts; 00716 uint32_t elt; 00717 00718 num_elts = v->num_elts; 00719 *mag_out = 0; 00720 00721 for (elt = 0; elt < num_elts; elt++) 00722 { 00723 *mag_out += v->elts[ elt ] * v->elts[ elt ]; 00724 } 00725 00726 *mag_out = sqrt(*mag_out); 00727 #endif 00728 } 00729 00749 void normalize_vector_sum_f(Vector_f** v_out, const Vector_f* v_in) 00750 { 00751 float sum; 00752 00753 calc_vector_asum_f(&sum, v_in); 00754 00755 if (sum > 0) 00756 { 00757 multiply_vector_by_scalar_f(v_out, v_in, 1.0f / sum); 00758 } 00759 else if (v_in != *v_out) 00760 { 00761 copy_vector_f(v_out, v_in); 00762 } 00763 } 00764 00772 void normalize_vector_sum_d(Vector_d** v_out, const Vector_d* v_in) 00773 { 00774 double sum; 00775 00776 calc_vector_asum_d(&sum, v_in); 00777 00778 if (sum > 0) 00779 { 00780 multiply_vector_by_scalar_d(v_out, v_in, 1.0 / sum); 00781 } 00782 else if (v_in != *v_out) 00783 { 00784 copy_vector_d(v_out, v_in); 00785 } 00786 } 00787 00807 void normalize_vector_mag_f(Vector_f** v_out, const Vector_f* v_in) 00808 { 00809 float mag; 00810 00811 calc_vector_mag_f(&mag, v_in); 00812 00813 if (mag > 0) 00814 { 00815 multiply_vector_by_scalar_f(v_out, v_in, 1.0f / mag); 00816 } 00817 else if (v_in != *v_out) 00818 { 00819 copy_vector_f(v_out, v_in); 00820 } 00821 } 00822 00830 void normalize_vector_mag_d(Vector_d** v_out, const Vector_d* v_in) 00831 { 00832 double mag; 00833 00834 calc_vector_mag_d(&mag, v_in); 00835 00836 if (mag > 0) 00837 { 00838 multiply_vector_by_scalar_d(v_out, v_in, 1.0 / mag); 00839 } 00840 else if (v_in != *v_out) 00841 { 00842 copy_vector_d(v_out, v_in); 00843 } 00844 } 00845 00873 Error* add_vectors_f 00874 ( 00875 Vector_f** v_out, 00876 const Vector_f* v_1, 00877 const Vector_f* v_2 00878 ) 00879 { 00880 uint32_t num_elts; 00881 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00882 #else 00883 uint32_t elt; 00884 #endif 00885 00886 if (v_1->num_elts != v_2->num_elts) 00887 { 00888 if (*v_out != v_1 && *v_out != v_2) 00889 { 00890 free_vector_f(*v_out); *v_out = NULL; 00891 } 00892 return JWSC_EARG("Adding vectors requires equal dimensions"); 00893 } 00894 00895 num_elts = v_1->num_elts; 00896 00897 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00898 if (*v_out == v_1) 00899 { 00900 blas_saxpy(num_elts, 1, v_2->elts, 1, v_1->elts, 1); 00901 } 00902 else if (*v_out == v_2) 00903 { 00904 blas_saxpy(num_elts, 1, v_1->elts, 1, v_2->elts, 1); 00905 } 00906 else 00907 { 00908 copy_vector_f(v_out, v_2); 00909 blas_saxpy(num_elts, 1, v_1->elts, 1, (*v_out)->elts, 1); 00910 } 00911 #else 00912 if (*v_out == v_1) 00913 { 00914 for (elt = 0; elt < num_elts; elt++) 00915 { 00916 v_1->elts[ elt ] += v_2->elts[ elt ]; 00917 } 00918 } 00919 else if (*v_out == v_2) 00920 { 00921 for (elt = 0; elt < num_elts; elt++) 00922 { 00923 v_2->elts[ elt ] += v_1->elts[ elt ]; 00924 } 00925 } 00926 else 00927 { 00928 create_vector_f(v_out, num_elts); 00929 for (elt = 0; elt < num_elts; elt++) 00930 { 00931 (*v_out)->elts[ elt ] = v_1->elts[ elt ] + v_2->elts[ elt ]; 00932 } 00933 } 00934 #endif 00935 00936 return NULL; 00937 } 00938 00954 Error* add_vectors_d 00955 ( 00956 Vector_d** v_out, 00957 const Vector_d* v_1, 00958 const Vector_d* v_2 00959 ) 00960 { 00961 uint32_t num_elts; 00962 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00963 #else 00964 uint32_t elt; 00965 #endif 00966 00967 if (v_1->num_elts != v_2->num_elts) 00968 { 00969 if (*v_out != v_1 && *v_out != v_2) 00970 { 00971 free_vector_d(*v_out); *v_out = NULL; 00972 } 00973 return JWSC_EARG("Adding vectors requires equal dimensions"); 00974 } 00975 00976 num_elts = v_1->num_elts; 00977 00978 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 00979 if (*v_out == v_1) 00980 { 00981 blas_daxpy(num_elts, 1, v_2->elts, 1, v_1->elts, 1); 00982 } 00983 else if (*v_out == v_2) 00984 { 00985 blas_daxpy(num_elts, 1, v_1->elts, 1, v_2->elts, 1); 00986 } 00987 else 00988 { 00989 copy_vector_d(v_out, v_2); 00990 blas_daxpy(num_elts, 1, v_1->elts, 1, (*v_out)->elts, 1); 00991 } 00992 #else 00993 if (*v_out == v_1) 00994 { 00995 for (elt = 0; elt < num_elts; elt++) 00996 { 00997 v_1->elts[ elt ] += v_2->elts[ elt ]; 00998 } 00999 } 01000 else if (*v_out == v_2) 01001 { 01002 for (elt = 0; elt < num_elts; elt++) 01003 { 01004 v_2->elts[ elt ] += v_1->elts[ elt ]; 01005 } 01006 } 01007 else 01008 { 01009 create_vector_d(v_out, num_elts); 01010 for (elt = 0; elt < num_elts; elt++) 01011 { 01012 (*v_out)->elts[ elt ] = v_1->elts[ elt ] + v_2->elts[ elt ]; 01013 } 01014 } 01015 #endif 01016 01017 return NULL; 01018 } 01019 01035 Error* add_vectors_cf 01036 ( 01037 Vector_cf** v_out, 01038 const Vector_cf* v_1, 01039 const Vector_cf* v_2 01040 ) 01041 { 01042 uint32_t num_elts; 01043 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01044 Complex_f z = {1, 0}; 01045 #else 01046 uint32_t elt; 01047 #endif 01048 01049 if (v_1->num_elts != v_2->num_elts) 01050 { 01051 if (*v_out != v_1 && *v_out != v_2) 01052 { 01053 free_vector_cf(*v_out); *v_out = NULL; 01054 } 01055 return JWSC_EARG("Adding vectors requires equal dimensions"); 01056 } 01057 01058 num_elts = v_1->num_elts; 01059 01060 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01061 if (*v_out == v_1) 01062 { 01063 blas_caxpy(num_elts, z, v_2->elts, 1, v_1->elts, 1); 01064 } 01065 else if (*v_out == v_2) 01066 { 01067 blas_caxpy(num_elts, z, v_1->elts, 1, v_2->elts, 1); 01068 } 01069 else 01070 { 01071 copy_vector_cf(v_out, v_2); 01072 blas_caxpy(num_elts, z, v_1->elts, 1, (*v_out)->elts, 1); 01073 } 01074 #else 01075 if (*v_out == v_1) 01076 { 01077 for (elt = 0; elt < num_elts; elt++) 01078 { 01079 v_1->elts[ elt ].r = v_1->elts[ elt ].r + v_2->elts[ elt ].r; 01080 v_1->elts[ elt ].i = v_1->elts[ elt ].i + v_2->elts[ elt ].i; 01081 } 01082 } 01083 else if (*v_out == v_2) 01084 { 01085 for (elt = 0; elt < num_elts; elt++) 01086 { 01087 v_2->elts[ elt ].r = v_1->elts[ elt ].r + v_2->elts[ elt ].r; 01088 v_2->elts[ elt ].i = v_1->elts[ elt ].i + v_2->elts[ elt ].i; 01089 } 01090 } 01091 else 01092 { 01093 create_vector_cf(v_out, num_elts); 01094 for (elt = 0; elt < num_elts; elt++) 01095 { 01096 (*v_out)->elts[ elt ].r = v_1->elts[ elt ].r + v_2->elts[ elt ].r; 01097 (*v_out)->elts[ elt ].i = v_1->elts[ elt ].i + v_2->elts[ elt ].i; 01098 } 01099 } 01100 #endif 01101 01102 return NULL; 01103 } 01104 01120 Error* add_vectors_cd 01121 ( 01122 Vector_cd** v_out, 01123 const Vector_cd* v_1, 01124 const Vector_cd* v_2 01125 ) 01126 { 01127 uint32_t num_elts; 01128 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01129 Complex_d z = {1, 0}; 01130 #else 01131 uint32_t elt; 01132 #endif 01133 01134 if (v_1->num_elts != v_2->num_elts) 01135 { 01136 if (*v_out != v_1 && *v_out != v_2) 01137 { 01138 free_vector_cd(*v_out); *v_out = NULL; 01139 } 01140 return JWSC_EARG("Adding vectors requires equal dimensions"); 01141 } 01142 01143 num_elts = v_1->num_elts; 01144 01145 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01146 if (*v_out == v_1) 01147 { 01148 blas_zaxpy(num_elts, z, v_2->elts, 1, v_1->elts, 1); 01149 } 01150 else if (*v_out == v_2) 01151 { 01152 blas_zaxpy(num_elts, z, v_1->elts, 1, v_2->elts, 1); 01153 } 01154 else 01155 { 01156 copy_vector_cd(v_out, v_2); 01157 blas_zaxpy(num_elts, z, v_1->elts, 1, (*v_out)->elts, 1); 01158 } 01159 #else 01160 if (*v_out == v_1) 01161 { 01162 for (elt = 0; elt < num_elts; elt++) 01163 { 01164 v_1->elts[ elt ].r = v_1->elts[ elt ].r + v_2->elts[ elt ].r; 01165 v_1->elts[ elt ].i = v_1->elts[ elt ].i + v_2->elts[ elt ].i; 01166 } 01167 } 01168 else if (*v_out == v_2) 01169 { 01170 for (elt = 0; elt < num_elts; elt++) 01171 { 01172 v_2->elts[ elt ].r = v_1->elts[ elt ].r + v_2->elts[ elt ].r; 01173 v_2->elts[ elt ].i = v_1->elts[ elt ].i + v_2->elts[ elt ].i; 01174 } 01175 } 01176 else 01177 { 01178 create_vector_cd(v_out, num_elts); 01179 for (elt = 0; elt < num_elts; elt++) 01180 { 01181 (*v_out)->elts[ elt ].r = v_1->elts[ elt ].r + v_2->elts[ elt ].r; 01182 (*v_out)->elts[ elt ].i = v_1->elts[ elt ].i + v_2->elts[ elt ].i; 01183 } 01184 } 01185 #endif 01186 01187 return NULL; 01188 } 01189 01217 Error* subtract_vectors_f 01218 ( 01219 Vector_f** v_out, 01220 const Vector_f* v_1, 01221 const Vector_f* v_2 01222 ) 01223 { 01224 uint32_t num_elts; 01225 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01226 Vector_f* v = NULL; 01227 #else 01228 uint32_t elt; 01229 #endif 01230 01231 if (v_1->num_elts != v_2->num_elts) 01232 { 01233 if (*v_out != v_1 && *v_out != v_2) 01234 { 01235 free_vector_f(*v_out); *v_out = NULL; 01236 } 01237 return JWSC_EARG("Subtracting vectors requires equal dimensions"); 01238 } 01239 01240 num_elts = v_1->num_elts; 01241 01242 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01243 if (*v_out == v_1) 01244 { 01245 blas_saxpy(num_elts, -1, v_2->elts, 1, v_1->elts, 1); 01246 } 01247 else if (*v_out == v_2) 01248 { 01249 copy_vector_f(&v, v_1); 01250 blas_saxpy(num_elts, -1, v_2->elts, 1, v->elts, 1); 01251 copy_vector_f(v_out, v); 01252 free_vector_f(v); 01253 } 01254 else 01255 { 01256 copy_vector_f(v_out, v_1); 01257 blas_saxpy(num_elts, -1, v_2->elts, 1, (*v_out)->elts, 1); 01258 } 01259 #else 01260 if (*v_out == v_1) 01261 { 01262 for (elt = 0; elt < num_elts; elt++) 01263 { 01264 v_1->elts[ elt ] = v_1->elts[ elt ] - v_2->elts[ elt ]; 01265 } 01266 } 01267 else if (*v_out == v_2) 01268 { 01269 for (elt = 0; elt < num_elts; elt++) 01270 { 01271 v_2->elts[ elt ] = v_1->elts[ elt ] - v_2->elts[ elt ]; 01272 } 01273 } 01274 else 01275 { 01276 create_vector_f(v_out, num_elts); 01277 for (elt = 0; elt < num_elts; elt++) 01278 { 01279 (*v_out)->elts[ elt ] = v_1->elts[ elt ] - v_2->elts[ elt ]; 01280 } 01281 } 01282 #endif 01283 01284 return NULL; 01285 } 01286 01302 Error* subtract_vectors_d 01303 ( 01304 Vector_d** v_out, 01305 const Vector_d* v_1, 01306 const Vector_d* v_2 01307 ) 01308 { 01309 uint32_t num_elts; 01310 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01311 Vector_d* v = NULL; 01312 #else 01313 uint32_t elt; 01314 #endif 01315 01316 if (v_1->num_elts != v_2->num_elts) 01317 { 01318 if (*v_out != v_1 && *v_out != v_2) 01319 { 01320 free_vector_d(*v_out); *v_out = NULL; 01321 } 01322 return JWSC_EARG("Subtracting vectors requires equal dimensions"); 01323 } 01324 01325 num_elts = v_1->num_elts; 01326 01327 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01328 if (*v_out == v_1) 01329 { 01330 blas_daxpy(num_elts, -1, v_2->elts, 1, v_1->elts, 1); 01331 } 01332 else if (*v_out == v_2) 01333 { 01334 copy_vector_d(&v, v_1); 01335 blas_daxpy(num_elts, -1, v_2->elts, 1, v->elts, 1); 01336 copy_vector_d(v_out, v); 01337 free_vector_d(v); 01338 } 01339 else 01340 { 01341 copy_vector_d(v_out, v_1); 01342 blas_daxpy(num_elts, -1, v_2->elts, 1, (*v_out)->elts, 1); 01343 } 01344 #else 01345 if (*v_out == v_1) 01346 { 01347 for (elt = 0; elt < num_elts; elt++) 01348 { 01349 v_1->elts[ elt ] = v_1->elts[ elt ] - v_2->elts[ elt ]; 01350 } 01351 } 01352 else if (*v_out == v_2) 01353 { 01354 for (elt = 0; elt < num_elts; elt++) 01355 { 01356 v_2->elts[ elt ] = v_1->elts[ elt ] - v_2->elts[ elt ]; 01357 } 01358 } 01359 else 01360 { 01361 create_vector_d(v_out, num_elts); 01362 for (elt = 0; elt < num_elts; elt++) 01363 { 01364 (*v_out)->elts[ elt ] = v_1->elts[ elt ] - v_2->elts[ elt ]; 01365 } 01366 } 01367 #endif 01368 01369 return NULL; 01370 } 01371 01387 Error* subtract_vectors_cf 01388 ( 01389 Vector_cf** v_out, 01390 const Vector_cf* v_1, 01391 const Vector_cf* v_2 01392 ) 01393 { 01394 uint32_t num_elts; 01395 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01396 Vector_cf* v = NULL; 01397 Complex_f z = {-1, 0}; 01398 #else 01399 uint32_t elt; 01400 #endif 01401 01402 if (v_1->num_elts != v_2->num_elts) 01403 { 01404 if (*v_out != v_1 && *v_out != v_2) 01405 { 01406 free_vector_cf(*v_out); *v_out = NULL; 01407 } 01408 return JWSC_EARG("Subtracting vectors requires equal dimensions"); 01409 } 01410 01411 num_elts = v_1->num_elts; 01412 01413 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01414 if (*v_out == v_1) 01415 { 01416 blas_caxpy(num_elts, z, v_2->elts, 1, v_1->elts, 1); 01417 } 01418 else if (*v_out == v_2) 01419 { 01420 copy_vector_cf(&v, v_1); 01421 blas_caxpy(num_elts, z, v_2->elts, 1, v->elts, 1); 01422 copy_vector_cf(v_out, v); 01423 free_vector_cf(v); 01424 } 01425 else 01426 { 01427 copy_vector_cf(v_out, v_1); 01428 blas_caxpy(num_elts, z, v_2->elts, 1, (*v_out)->elts, 1); 01429 } 01430 #else 01431 if (*v_out == v_1) 01432 { 01433 for (elt = 0; elt < num_elts; elt++) 01434 { 01435 v_1->elts[ elt ].r = v_1->elts[ elt ].r - v_2->elts[ elt ].r; 01436 v_1->elts[ elt ].i = v_1->elts[ elt ].i - v_2->elts[ elt ].i; 01437 } 01438 } 01439 else if (*v_out == v_2) 01440 { 01441 for (elt = 0; elt < num_elts; elt++) 01442 { 01443 v_2->elts[ elt ].r = v_1->elts[ elt ].r - v_2->elts[ elt ].r; 01444 v_2->elts[ elt ].i = v_1->elts[ elt ].i - v_2->elts[ elt ].i; 01445 } 01446 } 01447 else 01448 { 01449 create_vector_cf(v_out, num_elts); 01450 for (elt = 0; elt < num_elts; elt++) 01451 { 01452 (*v_out)->elts[ elt ].r = v_1->elts[ elt ].r - v_2->elts[ elt ].r; 01453 (*v_out)->elts[ elt ].i = v_1->elts[ elt ].i - v_2->elts[ elt ].i; 01454 } 01455 } 01456 #endif 01457 01458 return NULL; 01459 } 01460 01476 Error* subtract_vectors_cd 01477 ( 01478 Vector_cd** v_out, 01479 const Vector_cd* v_1, 01480 const Vector_cd* v_2 01481 ) 01482 { 01483 uint32_t num_elts; 01484 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01485 Vector_cd* v = NULL; 01486 Complex_d z = {-1, 0}; 01487 #else 01488 uint32_t elt; 01489 #endif 01490 01491 if (v_1->num_elts != v_2->num_elts) 01492 { 01493 if (*v_out != v_1 && *v_out != v_2) 01494 { 01495 free_vector_cd(*v_out); *v_out = NULL; 01496 } 01497 return JWSC_EARG("Subtracting vectors requires equal dimensions"); 01498 } 01499 01500 num_elts = v_1->num_elts; 01501 01502 #if defined JWSC_HAVE_BLAS || defined JWSC_HAVE_ACCELERATE 01503 if (*v_out == v_1) 01504 { 01505 blas_zaxpy(num_elts, z, v_2->elts, 1, v_1->elts, 1); 01506 } 01507 else if (*v_out == v_2) 01508 { 01509 copy_vector_cd(&v, v_1); 01510 blas_zaxpy(num_elts, z, v_2->elts, 1, v->elts, 1); 01511 copy_vector_cd(v_out, v); 01512 free_vector_cd(v); 01513 } 01514 else 01515 { 01516 copy_vector_cd(v_out, v_1); 01517 blas_zaxpy(num_elts, z, v_2->elts, 1, (*v_out)->elts, 1); 01518 } 01519 #else 01520 if (*v_out == v_1) 01521 { 01522 for (elt = 0; elt < num_elts; elt++) 01523 { 01524 v_1->elts[ elt ].r = v_1->elts[ elt ].r - v_2->elts[ elt ].r; 01525 v_1->elts[ elt ].i = v_1->elts[ elt ].i - v_2->elts[ elt ].i; 01526 } 01527 } 01528 else if (*v_out == v_2) 01529 { 01530 for (elt = 0; elt < num_elts; elt++) 01531 { 01532 v_2->elts[ elt ].r = v_1->elts[ elt ].r - v_2->elts[ elt ].r; 01533 v_2->elts[ elt ].i = v_1->elts[ elt ].i - v_2->elts[ elt ].i; 01534 } 01535 } 01536 else 01537 { 01538 create_vector_cd(v_out, num_elts); 01539 for (elt = 0; elt < num_elts; elt++) 01540 { 01541 (*v_out)->elts[ elt ].r = v_1->elts[ elt ].r - v_2->elts[ elt ].r; 01542 (*v_out)->elts[ elt ].i = v_1->elts[ elt ].i - v_2->elts[ elt ].i; 01543 } 01544 } 01545 #endif 01546 01547 return NULL; 01548 } 01549