ambiguity_test.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014 Swift Navigation Inc.
00003  * Contact: Ian Horn <ian@swift-nav.com>
00004  *
00005  * This source is subject to the license found in the file 'LICENSE' which must
00006  * be be distributed together with this source. All other rights reserved.
00007  *
00008  * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
00009  * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
00010  * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
00011  */
00012 
00013 #include <clapack.h>
00014 #include <inttypes.h>
00015 #include <cblas.h>
00016 #include <stdio.h>
00017 #include <string.h>
00018 #include "ambiguity_test.h"
00019 #include "common.h"
00020 #include "constants.h"
00021 #include "linear_algebra.h"
00022 #include "single_diff.h"
00023 #include "amb_kf.h"
00024 #include "lambda.h"
00025 
00026 #define RAW_PHASE_BIAS_VAR 0
00027 #define DECORRELATED_PHASE_BIAS_VAR 0
00028 #define NUM_SEARCH_STDS 5
00029 #define LOG_PROB_RAT_THRESHOLD -90
00030 
00031 #define DEBUG_AMBIGUITY_TEST 0
00032 
00033 
00038 void create_ambiguity_test(ambiguity_test_t *amb_test)
00039 {
00040   static u8 pool_buff[MAX_HYPOTHESES*(sizeof(hypothesis_t) + sizeof(void *))];
00041   static memory_pool_t pool;
00042   amb_test->pool = &pool;
00043   memory_pool_init(amb_test->pool, MAX_HYPOTHESES, sizeof(hypothesis_t), pool_buff);
00044   amb_test->sats.num_sats = 0;
00045   amb_test->amb_check.initialized = 0;
00046 }
00047 
00050 s8 filter_all(void *arg, element_t *elem)
00051 {
00052   (void) arg; (void) elem;
00053   return false;
00054 }
00055 
00056 
00057 void reset_ambiguity_test(ambiguity_test_t *amb_test) //TODO is this even necessary? we may only need create_ambiguity_test
00058 {
00059   if (DEBUG_AMBIGUITY_TEST) {
00060       printf("<RESET_AMBIGUITY_TEST>\n");
00061   }
00062   u8 x = 0;
00063   memory_pool_filter(amb_test->pool, (void *) &x, &filter_all);
00064   /* Initialize pool with single element with num_dds = 0, i.e.
00065    * zero length N vector, i.e. no satellites. When we take the
00066    * product of this single element with the set of new satellites
00067    * we will just get a set of elements corresponding to the new sats. */
00068   hypothesis_t *empty_element = (hypothesis_t *)memory_pool_add(amb_test->pool);
00069   /* Start with ll = 0, just for the sake of argument. */
00070   empty_element->ll = 0;
00071   amb_test->sats.num_sats = 0;
00072   amb_test->amb_check.initialized = 0;
00073   if (DEBUG_AMBIGUITY_TEST) {
00074       printf("</RESET_AMBIGUITY_TEST>\n");
00075   }
00076 }
00077 
00078 
00079 void destroy_ambiguity_test(ambiguity_test_t *amb_test)
00080 {
00081   memory_pool_destroy(amb_test->pool);
00082 }
00083 
00084 
00094 void print_double_mtx(double *m, u32 _r, u32 _c) {
00095     for (u32 _i = 0; _i < (_r); _i++) {
00096       printf(" [% 12lf", (m)[_i*(_c) + 0]);
00097       for (u32 _j = 1; _j < (_c); _j++)
00098         printf(" % 12lf", (m)[_i*(_c) + _j]);
00099       printf("]\n");
00100     }
00101 }
00102 
00103 
00116 void print_pearson_mtx(double *m, u32 dim) {
00117     for (u32 _i = 0; _i < dim; _i++) {
00118       printf(" [% 12lf", m[_i*dim + 0] / sqrt(m[_i*dim + _i]) / sqrt(m[0]));
00119       for (u32 _j = 1; _j < dim; _j++)
00120         printf(" % 12lf", m[_i*dim + _j] / sqrt(m[_i*dim + _i]) / sqrt(m[_j * dim + _j]));
00121       printf("]\n");
00122     }
00123 }
00124 
00125 
00136 void print_s32_mtx_diff(u32 m, u32 n, s32 *mat1, s32 *mat2)
00137 {
00138   for (u32 i=0; i < m; i++) {
00139     for (u32 j=0; j < n; j++) {
00140       printf("%"PRId32", ", mat1[i*n + j] - mat2[i*n + j]);
00141     }
00142     printf("\n");
00143   }
00144   printf("\n");
00145 }
00146 
00153 void print_s32_mtx(u32 m, u32 n, s32 *mat)
00154 {
00155   for (u32 i=0; i < m; i++) {
00156     for (u32 j=0; j < n; j++) {
00157       printf("%"PRId32", ", mat[i*n + j]);
00158     }
00159     printf("\n");
00160   }
00161   printf("\n");
00162 }
00163 
00172 void print_s32_gemv(u32 m, u32 n, s32 *M, s32 *v)
00173 {
00174   s32 mv[m];
00175   memset(mv, 0, m * sizeof(s32));
00176   printf("[");
00177   for (u32 i=0; i < m; i++) {
00178     for (u32 j=0; j < n; j++) {
00179       mv[i] += M[i*n + j] * v[j];
00180     }
00181     if (i+1 == m) {
00182       printf("%"PRId32" ]\n", mv[i]);
00183     }
00184     else {
00185       printf("%"PRId32", ", mv[i]);
00186     }
00187   }
00188 }
00189 
00199 s8 get_single_hypothesis(ambiguity_test_t *amb_test, s32 *hyp_N)
00200 {
00201   if (memory_pool_n_allocated(amb_test->pool) == 1) {
00202     hypothesis_t hyp;
00203     memory_pool_to_array(amb_test->pool, &hyp);
00204     memcpy(hyp_N, hyp.N, (amb_test->sats.num_sats-1) * sizeof(s32));
00205     return 0;
00206   }
00207   return -1;
00208 }
00209 
00213 typedef struct {
00214   u8 num_dds;             
00215   s32 N[MAX_CHANNELS-1];  
00216   u8 found;               
00217 } fold_contains_t;
00218 
00226 void fold_contains(void *x, element_t *elem)
00227 {
00228   fold_contains_t *acc = (fold_contains_t *) x;
00229   hypothesis_t *hyp = (hypothesis_t *) elem;
00230   if (acc->found == 1) {
00231     return;
00232   }
00233   for (u8 i=0; i<acc->num_dds; i++) {
00234     if (hyp->N[i] != acc->N[i]) {
00235       return;
00236     }
00237   }
00238   acc->found = 1;
00239 }
00240 
00247 u8 ambiguity_test_pool_contains(ambiguity_test_t *amb_test, double *ambs)
00248 {
00249   fold_contains_t acc;
00250   acc.num_dds = amb_test->sats.num_sats-1;
00251   for (u8 i=0; i<acc.num_dds; i++) {
00252     acc.N[i] = lround(ambs[i]);
00253   }
00254   acc.found = 0;
00255   memory_pool_fold(amb_test->pool, (void *) &acc, &fold_contains);
00256   return acc.found;
00257 }
00258 
00259 
00263 typedef struct {
00264   u8 started;            
00265   double max_ll;         
00266   u8 num_dds;            
00267   s32 N[MAX_CHANNELS-1]; 
00268 } fold_mle_t; // fold omelette
00269 
00277 void fold_mle(void *x, element_t *elem)
00278 {
00279   hypothesis_t *hyp = (hypothesis_t *) elem;
00280   fold_mle_t *mle = (fold_mle_t *) x;
00281   if (mle->started == 0 || hyp->ll > mle->max_ll) {
00282     mle->started = 1;
00283     mle->max_ll = hyp->ll;
00284     memcpy(mle->N, hyp->N, mle->num_dds * sizeof(s32));
00285   }
00286 }
00287 
00296 void ambiguity_test_MLE_ambs(ambiguity_test_t *amb_test, s32 *ambs)
00297 {
00298   fold_mle_t mle;
00299   mle.started = 0;
00300   mle.num_dds = MAX(1,amb_test->sats.num_sats)-1;
00301   memory_pool_fold(amb_test->pool, (void *) &mle, &fold_mle);
00302   memcpy(ambs, mle.N, mle.num_dds * sizeof(s32));
00303 }
00304 
00324 void init_ambiguity_test(ambiguity_test_t *amb_test, u8 state_dim, u8 *float_prns, sdiff_t *sdiffs, double *float_mean,
00325                          double *float_cov, double *DE_mtx, double *obs_cov)
00326 {
00327   (void) sdiffs;
00328   u8 num_dds = state_dim;
00329   double float_cov_N[num_dds * num_dds];
00330 
00331   /* Re-shape float_cov to contain just ambiguity states. */
00332   for (u8 i=0; i<num_dds; i++) {
00333     for (u8 j=0; j<num_dds; j++) {
00334       float_cov_N[i*num_dds + j] = float_cov[i*state_dim + j]; //TODO this is just a memcpy
00335     }
00336   }
00337 
00338   /* Initialize pool with single element with num_dds = 0, i.e.
00339    * zero length N vector, i.e. no satellites. When we take the
00340    * product of this single element with the set of new satellites
00341    * we will just get a set of elements corresponding to the new sats. */
00342   hypothesis_t *empty_element = (hypothesis_t *)memory_pool_add(amb_test->pool); // only in init
00343   /* Start with ll = 0, just for the sake of argument. */
00344   empty_element->ll = 0; // only in init
00345   amb_test->sats.num_sats = 0; // only in init
00346   s32 Z_inv[num_dds * num_dds];
00347   s32 lower_bounds[num_dds];
00348   s32 upper_bounds[num_dds];
00349   u8 num_dds_to_add;
00350   s8 add_any_sats =  determine_sats_addition(amb_test,
00351                                              float_cov_N, num_dds, &float_mean[6],
00352                                              lower_bounds, upper_bounds, &num_dds_to_add,
00353                                              Z_inv);
00354 
00355   if (add_any_sats == 1) {
00356     add_sats(amb_test, float_prns[0], num_dds_to_add, &float_prns[1], lower_bounds, upper_bounds, Z_inv);
00357     /* Update the rest of the amb_test state with the new sats. */
00358     init_residual_matrices(&amb_test->res_mtxs, num_dds, DE_mtx, obs_cov); // only in init
00359   }
00360 
00361 }
00362 
00363 
00385 void update_ambiguity_test(double ref_ecef[3], double phase_var, double code_var,
00386                            ambiguity_test_t *amb_test, u8 state_dim, sdiff_t *sdiffs,
00387                            u8 changed_sats)
00388 {
00389   if (DEBUG_AMBIGUITY_TEST) {
00390     printf("<UPDATE_AMBIGUITY_TEST>\n");
00391   }
00392   u8 num_sdiffs = state_dim + 1;
00393 
00394   if (amb_test->sats.num_sats < 5) {
00395     if (DEBUG_AMBIGUITY_TEST) {
00396       printf("</UPDATE_AMBIGUITY_TEST>\n");
00397     }
00398     return;
00399   }
00400 
00401   sdiff_t ambiguity_sdiffs[amb_test->sats.num_sats];
00402   double ambiguity_dd_measurements[2*(amb_test->sats.num_sats-1)];
00403   s8 valid_sdiffs = make_ambiguity_dd_measurements_and_sdiffs(
00404       amb_test, num_sdiffs, sdiffs, ambiguity_dd_measurements, ambiguity_sdiffs);
00405 
00406   /* Error */
00407   if (valid_sdiffs != 0) {
00408     printf("update_ambiguity_test: Invalid sdiffs. return code: %i\n", valid_sdiffs);
00409     for (u8 k=0; k < num_sdiffs; k++) {
00410       printf("%u, ", sdiffs[k].prn);
00411     }
00412     printf("}\n");
00413     print_sats_management_short(&amb_test->sats);
00414     return;
00415   }
00416 
00417   if (1 == 1 || changed_sats == 1) { //TODO add logic about when to update DE
00418     double DE_mtx[(amb_test->sats.num_sats-1) * 3];
00419     assign_de_mtx(amb_test->sats.num_sats, ambiguity_sdiffs, ref_ecef, DE_mtx);
00420     double obs_cov[(amb_test->sats.num_sats-1) * (amb_test->sats.num_sats-1) * 4];
00421     memset(obs_cov, 0, (amb_test->sats.num_sats-1) * (amb_test->sats.num_sats-1) * 4 * sizeof(double));
00422     u8 num_dds = amb_test->sats.num_sats-1;
00423     for (u8 i=0; i<num_dds; i++) {
00424       for (u8 j=0; j<num_dds; j++) {
00425         u8 i_ = i+num_dds;
00426         u8 j_ = j+num_dds;
00427         if (i==j) {
00428           obs_cov[i*2*num_dds + j] = phase_var * 2;
00429           obs_cov[i_*2*num_dds + j_] = code_var * 2;
00430         }
00431         else {
00432           obs_cov[i*2*num_dds + j] = phase_var;
00433           obs_cov[i_*2*num_dds + j_] = code_var;
00434         }
00435       }
00436     }
00437     // MAT_PRINTF(DE_mtx, ((u32) amb_test->sats.num_sats-1), 3);
00438     // MAT_PRINTF(obs_cov, 2*num_dds, 2*num_dds);
00439     init_residual_matrices(&amb_test->res_mtxs, amb_test->sats.num_sats-1, DE_mtx, obs_cov);
00440   }
00441 
00442   test_ambiguities(amb_test, ambiguity_dd_measurements);
00443 
00444   if (DEBUG_AMBIGUITY_TEST) {
00445     printf("</UPDATE_AMBIGUITY_TEST>\n");
00446   }
00447 }
00448 
00449 
00454 u32 ambiguity_test_n_hypotheses(ambiguity_test_t *amb_test)
00455 {
00456   return memory_pool_n_allocated(amb_test->pool);
00457 }
00458 
00462 typedef struct {
00463   u8 num_dds;                                 
00464   double r_vec[2*MAX_CHANNELS-5];             
00465   double max_ll;                              
00466   residual_mtxs_t *res_mtxs;                  
00467   unanimous_amb_check_t *unanimous_amb_check; 
00468 } hyp_filter_t;
00469 
00480 void update_and_get_max_ll(void *x_, element_t *elem) {
00481   hyp_filter_t *x = (hyp_filter_t *) x_;
00482   hypothesis_t *hyp = (hypothesis_t *) elem;
00483   double hypothesis_N[x->num_dds];
00484 
00485   for (u8 i=0; i < x->num_dds; i++) {
00486     hypothesis_N[i] = hyp->N[i];
00487   }
00488 
00489   hyp->ll += get_quadratic_term(x->res_mtxs, x->num_dds, hypothesis_N, x->r_vec);
00490   x->max_ll = MAX(x->max_ll, hyp->ll);
00491 }
00492 
00498 void check_unanimous_ambs(u8 num_dds, hypothesis_t *hyp,
00499                           unanimous_amb_check_t *amb_check)
00500 {
00501   if (amb_check->initialized) {
00502     u8 j = 0; // index in newly constructed amb_check matches
00503     for (u8 i = 0; i < amb_check->num_matching_ndxs; i++) {
00504       if (amb_check->ambs[i] == hyp->N[amb_check->matching_ndxs[i]]) {
00505         if (i != j) { //  j <= i necessarily
00506           amb_check->matching_ndxs[j] = amb_check->matching_ndxs[i];
00507           amb_check->ambs[j] = amb_check->ambs[i];
00508         }
00509         j++;
00510       }
00511     }
00512     amb_check->num_matching_ndxs = j;
00513   } else {
00514     amb_check->initialized = 1;
00515     amb_check->num_matching_ndxs = num_dds;
00516     for (u8 i=0; i < num_dds; i++) {
00517       amb_check->matching_ndxs[i] = i;
00518     }
00519     memcpy(amb_check->ambs, hyp->N, num_dds * sizeof(s32));
00520   }
00521 }
00522 
00542 s8 filter_and_renormalize(void *arg, element_t *elem) {
00543   hypothesis_t *hyp = (hypothesis_t *) elem;
00544 
00545   u8 keep_it = (hyp->ll > LOG_PROB_RAT_THRESHOLD);
00546   if (keep_it) {
00547     hyp->ll -= ((hyp_filter_t *) arg)->max_ll;
00548   }
00549   return keep_it;
00550 }
00551 
00552 static void _check_unanimous(void *arg, element_t *elem)
00553 {
00554   hypothesis_t *hyp = (hypothesis_t *) elem;
00555 
00556   check_unanimous_ambs(((hyp_filter_t *) arg)->num_dds, hyp,
00557                        ((hyp_filter_t *) arg)->unanimous_amb_check);
00558 }
00559 
00560 void update_unanimous_ambiguities(ambiguity_test_t *amb_test)
00561 {
00562   hyp_filter_t x;
00563   if (amb_test->sats.num_sats <= 1) {
00564     amb_test->amb_check.num_matching_ndxs = 0;
00565     return;
00566   }
00567   x.num_dds = amb_test->sats.num_sats-1;
00568   x.unanimous_amb_check = &amb_test->amb_check;
00569   x.unanimous_amb_check->initialized = 0;
00570 
00571   memory_pool_map(amb_test->pool, (void *) &x, &_check_unanimous);
00572 }
00573 
00574 /* Updates the IAR hypothesis pool log likelihood ratios and filters them.
00575  *  It assumes that the observations are structured to match the amb_test sats.
00576  *  INVALIDATES unanimous ambiguities
00577  */
00578 void test_ambiguities(ambiguity_test_t *amb_test, double *dd_measurements)
00579 {
00580   if (DEBUG_AMBIGUITY_TEST) {
00581     printf("<TEST_AMBIGUITIES>\n");
00582   }
00583   hyp_filter_t x;
00584   x.num_dds = amb_test->sats.num_sats-1;
00585   assign_r_vec(&amb_test->res_mtxs, x.num_dds, dd_measurements, x.r_vec);
00586   // VEC_PRINTF(x.r_vec, amb_test->res_mtxs.res_dim);
00587   x.max_ll = -1e20; //TODO get the first element, or use this as threshold to restart test
00588   x.res_mtxs = &amb_test->res_mtxs;
00589   x.unanimous_amb_check = &amb_test->amb_check;
00590   x.unanimous_amb_check->initialized = 0;
00591 
00592   memory_pool_fold(amb_test->pool, (void *) &x, &update_and_get_max_ll);
00593   /*memory_pool_map(amb_test->pool, &x.num_dds, &print_hyp);*/
00594   memory_pool_filter(amb_test->pool, (void *) &x, &filter_and_renormalize);
00595   if (memory_pool_empty(amb_test->pool)) {
00596       /* Initialize pool with single element with num_dds = 0, i.e.
00597      * zero length N vector, i.e. no satellites. When we take the
00598      * product of this single element with the set of new satellites
00599      * we will just get a set of elements corresponding to the new sats. */
00600     hypothesis_t *empty_element = (hypothesis_t *)memory_pool_add(amb_test->pool);
00601     /* Start with ll = 0, just for the sake of argument. */
00602     empty_element->ll = 0;
00603     amb_test->sats.num_sats = 0;
00604     amb_test->amb_check.initialized = 0;
00605   }
00606   if (DEBUG_AMBIGUITY_TEST) {
00607     memory_pool_map(amb_test->pool, &x.num_dds, &print_hyp);
00608     printf("num_unanimous_ndxs=%u\n</TEST_AMBIGUITIES>\n", x.unanimous_amb_check->num_matching_ndxs);
00609   }
00610 }
00611 
00612 /* This says whether we can use the ambiguity_test to resolve a position in 3-space.
00613  */
00614 u8 ambiguity_iar_can_solve(ambiguity_test_t *amb_test)
00615 {
00616   return amb_test->amb_check.initialized &&
00617          amb_test->amb_check.num_matching_ndxs >= 3;
00618 }
00619 
00620 bool is_prn_set(u8 len, u8 *prns)
00621 {
00622   if (len == 0) {
00623     return true;
00624   }
00625   u8 current = prns[0];
00626   for (u8 i = 1; i < len; i++) {
00627     if (prns[i] <= current) {
00628       return false;
00629     }
00630     current = prns[i];
00631   }
00632   return true;
00633 }
00634 
00635 /* Constructs the double differenced measurements and sdiffs needed for IAR.
00636  * This requires that all IAR prns are in the sdiffs used (sdiffs is a superset
00637  * of IAR's PRNs), that the sdiffs are ordered by prn, and that the IAR
00638  * non_ref_prns are also ordered (both ascending).
00639  *
00640  * The ambiguity_dd_measurements output will be ordered like the non_ref_prns
00641  * with the whole vector of carrier phase elements coming before the
00642  * pseudoranges. The amb_sdiffs will have the ref sat first, then the rest in
00643  * ascending order like the non_ref_prns.
00644  *
00645  * \param ref_prn                    The current reference PRN for the IAR.
00646  * \param non_ref_prns               The rest of the current PRNs for the IAR.
00647  * \param num_dds                    The number of dds used in the IAR
00648  *                                   (length of non_ref_prns).
00649  * \param num_sdiffs                 The number of sdiffs being passed in.
00650  * \param sdiffs                     The sdiffs to pull measurements out of.
00651  * \param ambiguity_dd_measurements  The output vector of DD measurements
00652  *                                   to be used to update the IAR.
00653  * \param amb_sdiffs                 The sdiffs that correspond to the IAR PRNs.
00654  * \return 0 if the input sdiffs are superset of the IAR sats,
00655  *        -1 if they are not,
00656  *        -2 if non_ref_prns is not an ordered set.
00657  */
00658 s8 make_dd_measurements_and_sdiffs(u8 ref_prn, u8 *non_ref_prns, u8 num_dds,
00659                                    u8 num_sdiffs, sdiff_t *sdiffs,
00660                                    double *ambiguity_dd_measurements, sdiff_t *amb_sdiffs)
00661 {
00662   if (DEBUG_AMBIGUITY_TEST) {
00663     printf("<MAKE_DD_MEASUREMENTS_AND_SDIFFS>\n");
00664     printf("ref_prn = %u\nnon_ref_prns = {", ref_prn);
00665     for (u8 i=0; i < num_dds; i++) {
00666       printf("%d, ", non_ref_prns[i]);
00667     }
00668     printf("}\nnum_dds = %u\nnum_sdiffs = %u\nsdiffs[*].prn = {", num_dds, num_sdiffs);
00669     for (u8 i=0; i < num_sdiffs; i++) {
00670       printf("%d, ", sdiffs[i].prn);
00671     }
00672     printf("}\n");
00673   }
00674 
00675   if (!is_prn_set(num_dds, non_ref_prns)) {
00676     printf("There is disorder in the amb_test sats.\n");
00677     printf("amb_test sat prns = {%u, ", ref_prn);
00678     for (u8 k=0; k < num_dds; k++) {
00679       printf("%u, ", non_ref_prns[k]);
00680     }
00681     printf("}\n");
00682     return -2;
00683   }
00684 
00685   double ref_phase = 0;
00686   double ref_pseudorange = 0;
00687   u8 i=0;
00688   u8 j=0;
00689   u8 found_ref = 0;
00690   /* Go through the sdiffs, pulling out the measurements of the non-ref amb sats
00691    * and the reference sat. */
00692   while (i < num_dds) {
00693     if (non_ref_prns[i] == sdiffs[j].prn) {
00694       /* When we find a non-ref sat, we fill in the next measurement. */
00695       memcpy(&amb_sdiffs[i+1], &sdiffs[j], sizeof(sdiff_t));
00696       ambiguity_dd_measurements[i] = sdiffs[j].carrier_phase;
00697       ambiguity_dd_measurements[i+num_dds] = sdiffs[j].pseudorange;
00698       i++;
00699       j++;
00700     } else if (ref_prn == sdiffs[j].prn) {
00701       /* when we find the ref sat, we copy it over and raise the FOUND flag */
00702       memcpy(&amb_sdiffs[0], &sdiffs[j], sizeof(sdiff_t));
00703       ref_phase =  sdiffs[j].carrier_phase;
00704       ref_pseudorange = sdiffs[j].pseudorange;
00705       j++;
00706       found_ref = 1;
00707     }
00708     else if (non_ref_prns[i] > sdiffs[j].prn) {
00709       /* If both sets are ordered, and we increase j (and possibly i), and the
00710        * i prn is higher than the j one, it means that the i one might be in the 
00711        * j set for higher j, and that the current j prn isn't in the i set. */
00712       j++;
00713     } else {
00714       /* if both sets are ordered, and we increase j (and possibly i), and the
00715        * j prn is higher than the i one, it means that the j one might be in the 
00716        * i set for higher i, and that the current i prn isn't in the j set.
00717        * This means a sat in the IAR's sdiffs isn't in the sdiffs.
00718        * */
00719       return -1;
00720     }
00721   }
00722   /* This awkward case deals with the situation when sdiffs and sats have the
00723    * same satellites only the ref of amb_test.sats is the last PRN in sdiffs.
00724    * This case is never checked for j = num_dds as i only runs to num_dds-1. */
00725   /* TODO: This function could be refactored to be a lot clearer. */
00726   while (!found_ref && j < num_sdiffs ) {
00727     if (ref_prn == sdiffs[j].prn) {
00728       memcpy(&amb_sdiffs[0], &sdiffs[j], sizeof(sdiff_t));
00729       ref_phase =  sdiffs[j].carrier_phase;
00730       ref_pseudorange = sdiffs[j].pseudorange;
00731       found_ref = 1;
00732     }
00733     j++;
00734   }
00735 
00736   if (found_ref == 0) {
00737     return -1;
00738   }
00739   for (u8 i=0; i < num_dds; i++) {
00740     ambiguity_dd_measurements[i] -= ref_phase;
00741     ambiguity_dd_measurements[i+num_dds] -= ref_pseudorange;
00742   }
00743   if (DEBUG_AMBIGUITY_TEST) {
00744     printf("amb_sdiff_prns = {");
00745     for (i = 0; i < num_dds; i++) {
00746       printf("%u, ", amb_sdiffs[i].prn);
00747     }
00748     printf("}\ndd_measurements = {");
00749     for (i=0; i < 2 * num_dds; i++) {
00750       printf("%f, \t", ambiguity_dd_measurements[i]);
00751     }
00752     printf("}\n</MAKE_DD_MEASUREMENTS_AND_SDIFFS>\n");
00753   }
00754   return 0;
00755 }
00756 
00757 
00778 s8 make_ambiguity_resolved_dd_measurements_and_sdiffs(
00779             ambiguity_test_t *amb_test, u8 num_sdiffs, sdiff_t *sdiffs,
00780             double *ambiguity_dd_measurements, sdiff_t *amb_sdiffs)
00781 {
00782   if (DEBUG_AMBIGUITY_TEST) {
00783     printf("<MAKE_AMBIGUITY_RESOLVED_DD_MEASUREMENTS_AND_SDIFFS>\n");
00784     printf("amb_test->sats.prns = {");
00785     for (u8 i=0; i < amb_test->sats.num_sats; i++) {
00786       printf("%u, ", amb_test->sats.prns[i]);
00787     }
00788     printf("}\n");
00789   }
00790 
00791   u8 ref_prn = amb_test->sats.prns[0];
00792   u8 num_dds = amb_test->amb_check.num_matching_ndxs;
00793   u8 non_ref_prns[num_dds];
00794   for (u8 i=0; i < num_dds; i++) {
00795     non_ref_prns[i] = amb_test->sats.prns[1 + amb_test->amb_check.matching_ndxs[i]];
00796     if (DEBUG_AMBIGUITY_TEST) {
00797       printf("non_ref_prns[%u] = %u, \t (ndx=%u) \t amb[%u] = %"PRId32"\n",
00798              i, non_ref_prns[i], amb_test->amb_check.matching_ndxs[i],
00799              i, amb_test->amb_check.ambs[i]);
00800     }
00801   }
00802   s8 valid_sdiffs =
00803     make_dd_measurements_and_sdiffs(ref_prn, non_ref_prns, num_dds, num_sdiffs,
00804                                     sdiffs, ambiguity_dd_measurements,
00805                                     amb_sdiffs);
00806   if (DEBUG_AMBIGUITY_TEST) {
00807     printf("</MAKE_AMBIGUITY_RESOLVED_DD_MEASUREMENTS_AND_SDIFFS>\n");
00808   }
00809   return valid_sdiffs;
00810 }
00811 
00812 
00827 s8 make_ambiguity_dd_measurements_and_sdiffs(ambiguity_test_t *amb_test, u8 num_sdiffs, sdiff_t *sdiffs,
00828                                                double *ambiguity_dd_measurements, sdiff_t *amb_sdiffs)
00829 {
00830   if (DEBUG_AMBIGUITY_TEST) {
00831     printf("<MAKE_AMBIGUITY_DD_MEASUREMENTS_AND_SDIFFS>\n");
00832   }
00833   u8 ref_prn = amb_test->sats.prns[0];
00834   u8 *non_ref_prns = &amb_test->sats.prns[1];
00835   u8 num_dds = MAX(1, amb_test->sats.num_sats)-1;
00836   s8 valid_sdiffs = make_dd_measurements_and_sdiffs(ref_prn, non_ref_prns,
00837                                   num_dds, num_sdiffs, sdiffs,
00838                                   ambiguity_dd_measurements, amb_sdiffs);
00839   if (DEBUG_AMBIGUITY_TEST) {
00840     printf("</MAKE_AMBIGUITY_DD_MEASUREMENTS_AND_SDIFFS>\n");
00841   }
00842   return valid_sdiffs;
00843 }
00844 
00845 
00846 s8 sats_match(ambiguity_test_t *amb_test, u8 num_sdiffs, sdiff_t *sdiffs)
00847 {
00848   if (DEBUG_AMBIGUITY_TEST) {
00849     printf("<SATS_MATCH>\namb_test.sats.prns = {");
00850     for (u8 i=0; i< amb_test->sats.num_sats; i++) {
00851       printf("%u, ", amb_test->sats.prns[i]);
00852     }
00853     printf("}\nsdiffs[*].prn      = {");
00854     for (u8 i=0; i < num_sdiffs; i++) {
00855       printf("%u, ", sdiffs[i].prn);
00856     }
00857     printf("}\n");
00858   }
00859   if (amb_test->sats.num_sats != num_sdiffs) {
00860     if (DEBUG_AMBIGUITY_TEST) {
00861       printf("sats don't match (different length)\n</SATS_MATCH>\n");
00862     }
00863     return 0;
00864   }
00865   u8 *prns = amb_test->sats.prns;
00866   u8 amb_ref = amb_test->sats.prns[0];
00867   u8 j=0;
00868   for (u8 i = 1; i<amb_test->sats.num_sats; i++) { //TODO will not having a j condition cause le fault du seg?
00869     if (j >= num_sdiffs) {
00870       if (DEBUG_AMBIGUITY_TEST) {
00871         printf("sats don't match\n</SATS_MATCH>\n");
00872       }
00873       return 0;
00874     }
00875     if (prns[i] == sdiffs[j].prn) {
00876       j++;
00877     }
00878     else if (amb_ref == sdiffs[j].prn) {
00879       j++;
00880       i--;
00881     }
00882     else {
00883       if (DEBUG_AMBIGUITY_TEST) {
00884         printf("sats don't match\n</SATS_MATCH>\n");
00885       }
00886       return 0;
00887     }
00888   }
00889   if (DEBUG_AMBIGUITY_TEST) {
00890     printf("sats match\n</SATS_MATCH>\n");
00891   }
00892   return 1;
00893 }
00894 
00895 typedef struct {
00896   u8 num_sats;
00897   u8 old_prns[MAX_CHANNELS];
00898   u8 new_prns[MAX_CHANNELS];
00899 } rebase_prns_t;
00900 
00901 void rebase_hypothesis(void *arg, element_t *elem) //TODO make it so it doesn't have to do all these lookups every time
00902 {
00903   rebase_prns_t *prns = (rebase_prns_t *) arg;
00904   u8 num_sats = prns->num_sats;
00905   u8 *old_prns = prns->old_prns;
00906   u8 *new_prns = prns->new_prns;
00907 
00908   hypothesis_t *hypothesis = (hypothesis_t *)elem;
00909 
00910   u8 old_ref = old_prns[0];
00911   u8 new_ref = new_prns[0];
00912 
00913   s32 new_N[num_sats-1];
00914   s32 index_of_new_ref_in_old = find_index_of_element_in_u8s(num_sats, new_ref, &old_prns[1]);
00915   s32 val_for_new_ref_in_old_basis = hypothesis->N[index_of_new_ref_in_old];
00916   for (u8 i=0; i<num_sats-1; i++) {
00917     u8 new_prn = new_prns[1+i];
00918     if (new_prn == old_ref) {
00919       new_N[i] = - val_for_new_ref_in_old_basis;
00920     }
00921     else {
00922       s32 index_of_this_sat_in_old_basis = find_index_of_element_in_u8s(num_sats, new_prn, &old_prns[1]);
00923       new_N[i] = hypothesis->N[index_of_this_sat_in_old_basis] - val_for_new_ref_in_old_basis;
00924     }
00925   }
00926   memcpy(hypothesis->N, new_N, (num_sats-1) * sizeof(s32));
00927 }
00928 
00929 u8 ambiguity_update_reference(ambiguity_test_t *amb_test, u8 num_sdiffs, sdiff_t *sdiffs, sdiff_t *sdiffs_with_ref_first)
00930 {
00931   if (DEBUG_AMBIGUITY_TEST) {
00932     printf("<AMBIGUITY_UPDATE_REFERENCE>\n");
00933   }
00934   u8 changed_ref = 0;
00935   u8 old_prns[amb_test->sats.num_sats];
00936   memcpy(old_prns, amb_test->sats.prns, amb_test->sats.num_sats * sizeof(u8));
00937 
00938   // print_sats_management_short(&amb_test->sats);
00939   s8 sats_management_code = rebase_sats_management(&amb_test->sats, num_sdiffs, sdiffs, sdiffs_with_ref_first);
00940   // print_sats_management_short(&amb_test->sats);
00941   if (sats_management_code != OLD_REF) {
00942     if (DEBUG_AMBIGUITY_TEST) {
00943       printf("updating iar reference sat\n");
00944     }
00945     changed_ref = 1;
00946     u8 new_prns[amb_test->sats.num_sats];
00947     memcpy(new_prns, amb_test->sats.prns, amb_test->sats.num_sats * sizeof(u8));
00948 
00949     rebase_prns_t prns = {.num_sats = amb_test->sats.num_sats};
00950     memcpy(prns.old_prns, old_prns, amb_test->sats.num_sats * sizeof(u8));
00951     memcpy(prns.new_prns, new_prns, amb_test->sats.num_sats * sizeof(u8));
00952     memory_pool_map(amb_test->pool, &prns, &rebase_hypothesis);
00953   }
00954   if (DEBUG_AMBIGUITY_TEST) {
00955     printf("</AMBIGUITY_UPDATE_REFERENCE>\n");
00956   }
00957   return changed_ref;
00958 }
00959 
00960 typedef struct {
00961   u8 num_ndxs;
00962   u8 intersection_ndxs[MAX_CHANNELS-1];
00963 } intersection_ndxs_t;
00964 
00965 s32 projection_comparator(void *arg, element_t *a, element_t *b)
00966 {
00967   intersection_ndxs_t *intersection_struct = (intersection_ndxs_t *) arg;
00968   u8 num_ndxs = intersection_struct->num_ndxs;
00969   u8 *intersection_ndxs = intersection_struct->intersection_ndxs;
00970 
00971   hypothesis_t *hyp_a = (hypothesis_t *) a;
00972   hypothesis_t *hyp_b = (hypothesis_t *) b;
00973 
00974   for (u8 i=0; i<num_ndxs; i++) {
00975     u8 ndxi = intersection_ndxs[i];
00976     s32 ai = hyp_a->N[ndxi];
00977     s32 bi = hyp_b->N[ndxi];
00978     if (ai == bi) {
00979       continue;
00980     }
00981     if (ai < bi) {
00982       return -1;
00983     }
00984     if (ai > bi) {
00985       return 1;
00986     }
00987   }
00988   return 0;
00989 }
00990 
00991 void projection_aggregator(element_t *new_, void *x_, u32 n, element_t *elem_)
00992 {
00993   intersection_ndxs_t *x = (intersection_ndxs_t *)x_;
00994   hypothesis_t *new = (hypothesis_t *)new_;
00995   hypothesis_t *elem = (hypothesis_t *)elem_;
00996 
00997   if (n == 0) {
00998     for (u8 i=0; i<x->num_ndxs; i++) {
00999       u8 ndxi = x->intersection_ndxs[i];
01000       new->N[i] = elem->N[ndxi];
01001     }
01002     new->ll = elem->ll;
01003   }
01004   else {
01005     new->ll += log(1 + exp(elem->ll - new->ll));
01006     // new->ll = MAX(new->ll, elem->ll);
01007   }
01008 
01009 }
01010 
01011 u8 ambiguity_sat_projection(ambiguity_test_t *amb_test, u8 num_dds_in_intersection, u8 *dd_intersection_ndxs)
01012 {
01013   if (DEBUG_AMBIGUITY_TEST) {
01014     printf("<AMBIGUITY_SAT_PROJECTION>\n");
01015   }
01016   u8 num_dds_before_proj = MAX(1, amb_test->sats.num_sats) - 1;
01017   if (num_dds_before_proj == num_dds_in_intersection) {
01018     if (DEBUG_AMBIGUITY_TEST) {
01019       printf("no need for projection\n</AMBIGUITY_SAT_PROJECTION>\n");
01020     }
01021     return 0;
01022   }
01023 
01024   intersection_ndxs_t intersection = {.num_ndxs = num_dds_in_intersection};
01025   memcpy(intersection.intersection_ndxs, dd_intersection_ndxs, num_dds_in_intersection * sizeof(u8));
01026 
01027 
01028   printf("IAR: %"PRIu32" hypotheses before projection\n", memory_pool_n_allocated(amb_test->pool));
01029   /*memory_pool_map(amb_test->pool, &num_dds_before_proj, &print_hyp);*/
01030   memory_pool_group_by(amb_test->pool,
01031                        &intersection, &projection_comparator,
01032                        &intersection, sizeof(intersection),
01033                        &projection_aggregator);
01034   printf("IAR: updates to %"PRIu32"\n", memory_pool_n_allocated(amb_test->pool));
01035   /*memory_pool_map(amb_test->pool, &num_dds_in_intersection, &print_hyp);*/
01036   u8 work_prns[MAX_CHANNELS];
01037   memcpy(work_prns, amb_test->sats.prns, amb_test->sats.num_sats * sizeof(u8));
01038   for (u8 i=0; i<num_dds_in_intersection; i++) {
01039     amb_test->sats.prns[i+1] = work_prns[dd_intersection_ndxs[i]+1];
01040   }
01041   amb_test->sats.num_sats = num_dds_in_intersection+1;
01042   if (DEBUG_AMBIGUITY_TEST) {
01043     printf("</AMBIGUITY_SAT_PROJECTION>\n");
01044   }
01045   return 1;
01046 }
01047 
01048 
01049 u8 ambiguity_sat_inclusion(ambiguity_test_t *amb_test, u8 num_dds_in_intersection,
01050                              sats_management_t *float_sats, double *float_mean, double *float_cov_U, double *float_cov_D)
01051 {
01052   if (DEBUG_AMBIGUITY_TEST) {
01053     printf("<AMBIGUITY_SAT_INCLUSION>\n");
01054   }
01055   if (float_sats->num_sats <= num_dds_in_intersection + 1 || float_sats->num_sats < 2) {
01056     if (DEBUG_AMBIGUITY_TEST) {
01057       printf("no need for inclusion\n</AMBIGUITY_SAT_INCLUSION>\n");
01058     }
01059     return 0;
01060   }
01061 
01062   u32 state_dim = float_sats->num_sats-1;
01063   double float_cov[state_dim * state_dim];
01064   matrix_reconstruct_udu(state_dim, float_cov_U, float_cov_D, float_cov);
01065   u8 float_prns[float_sats->num_sats];
01066   memcpy(float_prns, float_sats->prns, float_sats->num_sats * sizeof(u8));
01067   double N_mean[float_sats->num_sats-1];
01068   memcpy(N_mean, float_mean, (float_sats->num_sats-1) * sizeof(double));
01069   if (amb_test->sats.num_sats >= 2 && amb_test->sats.prns[0] != float_sats->prns[0]) {
01070     u8 old_prns[float_sats->num_sats];
01071     memcpy(old_prns, float_sats->prns, float_sats->num_sats * sizeof(u8));
01072     // memcpy(N_mean, &float_mean[6], (float_sats->num_sats-1) * sizeof(double));
01073     set_reference_sat_of_prns(amb_test->sats.prns[0], float_sats->num_sats, float_prns);
01074     rebase_mean_N(N_mean, float_sats->num_sats, old_prns, float_prns);
01075     rebase_covariance_sigma(float_cov, float_sats->num_sats, old_prns, float_prns);
01076   }
01077   double N_cov[(float_sats->num_sats-1) * (float_sats->num_sats-1)];
01078   memcpy(N_cov, float_cov, state_dim * state_dim * sizeof(double)); //TODO we can just use N_cov throughout
01079   //by now float_prns has the correct reference, as do N_cov and N_mean
01080 
01081   // MAT_PRINTF(float_cov, state_dim, state_dim);
01082   // MAT_PRINTF(N_cov, (u8)(float_sats->num_sats-1), (u8)(float_sats->num_sats-1));
01083 
01084   // printf("pearson mtx of float cov\n");
01085   // print_pearson_mtx(float_cov, state_dim);
01086   // printf("\n");
01087 
01088   // printf("pearson mtx of N cov\n");
01089   // print_pearson_mtx(N_cov, float_sats->num_sats-1);
01090   // printf("\n");
01091 
01092   //next we add the new sats
01093   //loop through the new sat sets in decreasing number (for now, in prn order), adding when it suits us
01094 
01095   /* first set up the largest prn lists of added sats
01096    * then get those prns covariances
01097    * then loop through:
01098    *    test if we'll add these
01099    *    if so:
01100    *      add them
01101    *      break loop
01102    *    else:
01103    *      decrease size of cov set
01104    */
01105 
01106   //first get all the prns we might add, and their covariances
01107   u8 i = 1;
01108   u8 j = 1;
01109   u8 num_addible_dds = 0;
01110   u8 ndxs_of_new_dds_in_float[MAX_CHANNELS-1];
01111   u8 new_dd_prns[MAX_CHANNELS-1];
01112   while (j < float_sats->num_sats) {
01113     if (i < amb_test->sats.num_sats && amb_test->sats.prns[i] == float_prns[j]) {
01114       i++;
01115       j++;
01116     } else { //else float_sats[j] is a new one
01117       ndxs_of_new_dds_in_float[num_addible_dds] = j-1;
01118       new_dd_prns[num_addible_dds] = float_prns[j];
01119       num_addible_dds++;
01120       j++;
01121     }
01122   }
01123 
01124   double addible_float_cov[num_addible_dds * num_addible_dds];
01125   double addible_float_mean[num_addible_dds];
01126   for (i=0; i < num_addible_dds; i++) {
01127     for (j=0; j < num_addible_dds; j++) {
01128       addible_float_cov[i*num_addible_dds + j] = N_cov[ndxs_of_new_dds_in_float[i]*(float_sats->num_sats-1) + ndxs_of_new_dds_in_float[j]];
01129     }
01130     addible_float_mean[i] = N_mean[ndxs_of_new_dds_in_float[i]];
01131   }
01132   // MAT_PRINTF(addible_float_cov, num_addible_dds, num_addible_dds);
01133   /*VEC_PRINTF(addible_float_mean, num_addible_dds);*/
01134 
01135   s32 Z_inv[num_addible_dds * num_addible_dds];
01136   s32 lower_bounds[num_addible_dds];
01137   s32 upper_bounds[num_addible_dds];
01138   u8 num_dds_to_add;
01139   s8 add_any_sats =  determine_sats_addition(amb_test,
01140                                              addible_float_cov, num_addible_dds, addible_float_mean,
01141                                              lower_bounds, upper_bounds, &num_dds_to_add,
01142                                              Z_inv);
01143 
01144   if (add_any_sats == 1) {
01145     add_sats(amb_test, float_prns[0], num_dds_to_add, new_dd_prns, lower_bounds, upper_bounds, Z_inv);
01146     if (DEBUG_AMBIGUITY_TEST) {
01147       printf("adding sats\n<AMBIGUITY_SAT_INCLUSION>\n");
01148     }
01149     return 1;
01150   } else {
01151     if (DEBUG_AMBIGUITY_TEST) {
01152       printf("not adding sats\n<AMBIGUITY_SAT_INCLUSION>\n");
01153     }
01154     return 0;
01155   }
01156 
01157 }
01158 
01159 u32 float_to_decor(ambiguity_test_t *amb_test,
01160                    double *addible_float_cov, u8 num_addible_dds,
01161                    double *addible_float_mean,
01162                    u8 num_dds_to_add,
01163                    s32 *lower_bounds, s32 *upper_bounds, double *Z)
01164 {
01165   (void) amb_test;
01166   double added_float_cov[num_dds_to_add * num_dds_to_add];
01167   for (u8 i=0; i<num_dds_to_add; i++) {
01168     for (u8 j=0; j<num_dds_to_add; j++) {
01169       added_float_cov[i*num_dds_to_add + j] = addible_float_cov[i*num_addible_dds + j];
01170       #if RAW_PHASE_BIAS_VAR != 0
01171       if (i == j) {
01172         added_float_cov[i*num_dds_to_add + j] += RAW_PHASE_BIAS_VAR;
01173       }
01174       #endif
01175     }
01176   }
01177 
01178   // double Z[num_dds_to_add * num_dds_to_add];
01179   lambda_reduction(num_dds_to_add, added_float_cov, Z);
01180 
01181   double decor_float_cov_diag[num_dds_to_add];
01182 
01183   memset(decor_float_cov_diag, 0, num_dds_to_add * sizeof(double));
01184 
01185   for (u8 i=0; i < num_dds_to_add; i++) {
01186     for (u8 j=0; j < num_dds_to_add; j++) {
01187       for (u8 k=0; k < num_dds_to_add; k++) {
01188         decor_float_cov_diag[i] += Z[i*num_dds_to_add + j] * added_float_cov[j * num_dds_to_add + k] * Z[i*num_dds_to_add + k];
01189       }
01190     }
01191     #if DECORRELATED_PHASE_BIAS_VAR != 0
01192     decor_float_cov_diag[i] += DECORRELATED_PHASE_BIAS_VAR;
01193     #endif
01194   }
01195 
01196   double decor_float_mean[num_dds_to_add];
01197   memset(decor_float_mean, 0, num_dds_to_add * sizeof(double));
01198   for (u8 i=0; i < num_dds_to_add; i++) {
01199     for (u8 j=0; j < num_dds_to_add; j++) {
01200       decor_float_mean[i] += Z[i*num_dds_to_add + j] * addible_float_mean[j];
01201     }
01202     // printf("decor_float_mean[%u] = %f\n", i, decor_float_mean[i]);
01203   }
01204 
01205   u32 new_hyp_set_cardinality = 1;
01206   // s32 lower_bounds[num_dds_to_add];
01207   // s32 upper_bounds[num_dds_to_add];
01208   for (u8 i=0; i<num_dds_to_add; i++) {
01209     double search_distance = NUM_SEARCH_STDS * sqrt(decor_float_cov_diag[i]);
01210     // upper_bounds[i] = MAX(floor(float_mean[i] + search_distance), ceil(float_mean[i]));
01211     // lower_bounds[i] = MIN(ceil(float_mean[i] - search_distance), floor(float_mean[i]));
01212     upper_bounds[i] = lround(ceil(decor_float_mean[i] + search_distance));
01213     lower_bounds[i] = lround(floor(decor_float_mean[i] - search_distance));
01214     new_hyp_set_cardinality *= upper_bounds[i] - lower_bounds[i] + 1;
01215   }
01216   return new_hyp_set_cardinality;
01217 }
01218 
01219 s8 determine_sats_addition(ambiguity_test_t *amb_test,
01220                            double *float_N_cov, u8 num_float_dds, double *float_N_mean,
01221                            s32 *lower_bounds, s32 *upper_bounds, u8 *num_dds_to_add,
01222                            s32 *Z_inv)
01223 {
01224   u8 num_current_dds = MAX(1, amb_test->sats.num_sats) - 1;
01225   u8 min_dds_to_add = MAX(1, 4 - num_current_dds); // num_current_dds + min_dds_to_add = 4 so that we have a nullspace projector
01226 
01227   u32 max_new_hyps_cardinality;
01228   s32 current_num_hyps = memory_pool_n_allocated(amb_test->pool);
01229   u32 max_num_hyps = memory_pool_n_elements(amb_test->pool);
01230   if (current_num_hyps <= 0) {
01231     max_new_hyps_cardinality = max_num_hyps;
01232   } else {
01233     max_new_hyps_cardinality = max_num_hyps / current_num_hyps;
01234   }
01235 
01236   // printf("pearson mtx of float N cov\n");
01237   // print_pearson_mtx(float_N_cov, num_float_dds);
01238   // printf("\n");
01239 
01240   *num_dds_to_add = num_float_dds;
01241   double Z[num_float_dds * num_float_dds];
01242   while (*num_dds_to_add >= min_dds_to_add) {
01243     u32 new_hyp_set_cardinality = float_to_decor(amb_test,
01244                                                  float_N_cov, num_float_dds,
01245                                                  float_N_mean,
01246                                                  *num_dds_to_add,
01247                                                  lower_bounds, upper_bounds, Z);
01248     if (new_hyp_set_cardinality <= max_new_hyps_cardinality) {
01249       double Z_inv_[*num_dds_to_add * *num_dds_to_add];
01250       matrix_inverse(*num_dds_to_add, Z, Z_inv_);
01251       /* TODO: Check return value of matrix_inverse to handle singular matrix. */
01252       for (u8 i=0; i < *num_dds_to_add; i++) {
01253         for (u8 j=0; j < *num_dds_to_add; j++) {
01254           Z_inv[i* *num_dds_to_add + j] = lround(Z_inv_[i* *num_dds_to_add + j]);
01255         }
01256       }
01257       return 1;
01258     }
01259     else {
01260       *num_dds_to_add -= 1;
01261     }
01262   }
01263   return -1;
01264 }
01265 
01266 
01267 // input/output: amb_test
01268 // input:        num_sdiffs
01269 // input:        sdiffs
01270 // input:        float_sats
01271 // input:        float_mean
01272 // input:        float_cov_U
01273 // input:        float_cov_D
01274 // INVALIDATES unanimous ambiguities
01275 u8 ambiguity_update_sats(ambiguity_test_t *amb_test, u8 num_sdiffs, sdiff_t *sdiffs,
01276                          sats_management_t *float_sats, double *float_mean, double *float_cov_U, double *float_cov_D)
01277 {
01278   if (DEBUG_AMBIGUITY_TEST) {
01279     printf("<AMBIGUITY_UPDATE_SATS>\n");
01280   }
01281   if (num_sdiffs < 2) {
01282     create_ambiguity_test(amb_test);
01283     if (DEBUG_AMBIGUITY_TEST) {
01284       printf("< 2 sdiffs, starting over\n</AMBIGUITY_UPDATE_SATS>\n");
01285     }
01286     return 0; // I chose 0 because it doesn't lead to anything dynamic
01287   }
01288   //if the sats are the same, we're good
01289   u8 changed_sats = 0;
01290   if (!sats_match(amb_test, num_sdiffs, sdiffs)) {
01291     sdiff_t sdiffs_with_ref_first[num_sdiffs];
01292     if (amb_test->sats.num_sats >= 2) {
01293       if (ambiguity_update_reference(amb_test, num_sdiffs, sdiffs, sdiffs_with_ref_first)) {
01294        changed_sats=1;
01295       }
01296     } else {
01297       create_ambiguity_test(amb_test);//we don't have what we need
01298     }
01299 
01300     u8 intersection_ndxs[num_sdiffs];
01301     u8 num_dds_in_intersection = find_indices_of_intersection_sats(amb_test, num_sdiffs, sdiffs_with_ref_first, intersection_ndxs);
01302 
01303     if (amb_test->sats.num_sats > 1 && num_dds_in_intersection == 0) {
01304       create_ambiguity_test(amb_test); //TODO is create_ambiguity_test any better than reset_ambiguity_test here? does reset even need to exist
01305     }
01306 
01307     // u8 num_dds_in_intersection = ambiguity_order_sdiffs_with_intersection(amb_test, sdiffs, float_cov, intersection_ndxs);
01308     if (ambiguity_sat_projection(amb_test, num_dds_in_intersection, intersection_ndxs)) {
01309       changed_sats = 1;
01310     }
01311     if (ambiguity_sat_inclusion(amb_test, num_dds_in_intersection,
01312                                 float_sats, float_mean, float_cov_U, float_cov_D)) {
01313       changed_sats = 1;
01314     }
01315   }
01316   if (DEBUG_AMBIGUITY_TEST) {
01317     printf("changed_sats = %u\n</AMBIGUITY_UPDATE_SATS>\n", changed_sats);
01318   }
01319 
01320   return changed_sats;
01321   /* TODO: Should we order by 'goodness'? Perhaps by volume of hyps? */
01322 }
01323 
01324 u8 find_indices_of_intersection_sats(ambiguity_test_t *amb_test, u8 num_sdiffs, sdiff_t *sdiffs_with_ref_first, u8 *intersection_ndxs)
01325 {
01326   if (DEBUG_AMBIGUITY_TEST) {
01327     printf("<FIND_INDICES_OF_INTERSECTION_SATS>\n");
01328     printf("amb_test->sats.prns          = {");
01329     for (u8 i = 0; i < amb_test->sats.num_sats; i++) {
01330       printf("%u, ", amb_test->sats.prns[i]);
01331     }
01332     if (amb_test->sats.num_sats < 2) {
01333       printf("}\nsdiffs_with_ref_first not populated\n");
01334     }
01335     else {
01336       printf("}\nsdiffs_with_ref_first[*].prn = {");
01337       for (u8 i = 0; i < num_sdiffs; i++) {
01338         printf("%u, ", sdiffs_with_ref_first[i].prn);
01339       }
01340       printf("}\n");
01341     }
01342     printf("(i, j, k, amb_test->sats.prns[i], sdiffs_with_ref_first[j].prn)\n");
01343   }
01344   u8 i = 1;
01345   u8 j = 1;
01346   u8 k = 0;
01347   while (i < amb_test->sats.num_sats && j < num_sdiffs) {
01348     if (amb_test->sats.prns[i] == sdiffs_with_ref_first[j].prn) {
01349       if (DEBUG_AMBIGUITY_TEST) {
01350         printf("(%u, \t%u, \t%u, \t%u, \t%u)\t\t\tamb_test->sats.prns[i] == sdiffs_with_ref_first[j].prn; i,j,k++\n",
01351                 i, j, k, amb_test->sats.prns[i], sdiffs_with_ref_first[j].prn);
01352       }
01353       intersection_ndxs[k] = i-1;
01354       i++;
01355       j++;
01356       k++;
01357     }
01358     else if (amb_test->sats.prns[i] < sdiffs_with_ref_first[j].prn) {
01359       if (DEBUG_AMBIGUITY_TEST) {
01360         printf("(%u, \t%u, \t%u, \t%u, \t%u)\t\t\tamb_test->sats.prns[i] <  sdiffs_with_ref_first[j].prn; i++\n",
01361                 i, j, k, amb_test->sats.prns[i], sdiffs_with_ref_first[j].prn);
01362       }
01363       i++;
01364     }
01365     else {
01366       if (DEBUG_AMBIGUITY_TEST) {
01367         printf("(%u, \t%u, \t%u, \t%u, \t%u)\t\t\tamb_test->sats.prns[i] >  sdiffs_with_ref_first[j].prn; j++\n",
01368                 i, j, k, amb_test->sats.prns[i], sdiffs_with_ref_first[j].prn);
01369       }
01370       j++;
01371     }
01372   }
01373   if (DEBUG_AMBIGUITY_TEST) {
01374     printf("</FIND_INDICES_OF_INTERSECTION_SATS>\n");
01375   }
01376   return k;
01377 }
01378 
01379 typedef struct {
01380   s32 upper_bounds[MAX_CHANNELS-1];
01381   s32 lower_bounds[MAX_CHANNELS-1];
01382   s32 counter[MAX_CHANNELS-1];
01383   u8 ndxs_of_old_in_new[MAX_CHANNELS-1];
01384   u8 ndxs_of_added_in_new[MAX_CHANNELS-1];
01385   u8 num_added_dds;
01386   u8 num_old_dds;
01387   s32 Z_inv[(MAX_CHANNELS-1) * (MAX_CHANNELS-1)];
01388 } generate_hypothesis_state_t;
01389 
01390 s8 generate_next_hypothesis(void *x_, u32 n)
01391 {
01392   (void) n;
01393   generate_hypothesis_state_t *x = (generate_hypothesis_state_t *)x_;
01394   // printf("generate_next_hypothesis:\n");
01395 
01396   if (memcmp(x->upper_bounds, x->counter, x->num_added_dds * sizeof(s32)) == 0) {
01397     /* counter has reached upper_bound, terminate iteration. */
01398     return 0;
01399   }
01400 
01401   for (u8 i=0; i<x->num_added_dds; i++) {
01402     x->counter[i]++;
01403     if (x->counter[i] > x->upper_bounds[i]) {
01404       /* counter[i] has reached maximum, reset counter[i]
01405        * to lower[i] and 'carry' to next 'digit' */
01406       x->counter[i] = x->lower_bounds[i];
01407     } else {
01408       /* Incremented, so now we have the next counter value. */
01409       break;
01410     }
01411   }
01412 
01413   // printf("[");
01414   // for (u8 i=0; i<x->num_added_dds; i++) {
01415   //   printf("%d, ", x->counter[i]);
01416   // }
01417   // printf("]\n\n");
01418 
01419   return 1;
01420 }
01421 
01422 void hypothesis_prod(element_t *new_, void *x_, u32 n, element_t *elem_)
01423 {
01424   (void) elem_;
01425   (void) n;
01426   generate_hypothesis_state_t *x = (generate_hypothesis_state_t *)x_;
01427   hypothesis_t *new = (hypothesis_t *) new_;
01428 
01429   u8 *ndxs_of_old_in_new = x->ndxs_of_old_in_new;
01430   u8 *ndxs_of_added_in_new = x->ndxs_of_added_in_new;
01431 
01432   s32 old_N[MAX_CHANNELS-1];
01433   memcpy(old_N, new->N, x->num_old_dds * sizeof(s32));
01434 
01435   // printf("counter: [");
01436   // for (u8 i=0; i < x->num_added_dds; i++) {
01437   //   printf("%d, ", x->counter[i]);
01438   // }
01439   // printf("]\n");
01440   // printf("old_N:ndx [");
01441   // for (u8 i=0; i < x->num_old_dds; i++) {
01442   //   printf("%d, ", ndxs_of_old_in_new[i]);
01443   // }
01444   // printf("]\n");
01445   // printf("old_N:    [");
01446   // for (u8 i=0; i < x->num_old_dds; i++) {
01447   //   printf("%d, ", old_N[i]);
01448   // }
01449   // printf("]\n");
01450 
01451   // printf("added_N:ndx [");
01452   // for (u8 i=0; i < x->num_added_dds; i++) {
01453   //   printf("%d, ", ndxs_of_added_in_new[i]);
01454   // }
01455   // printf("]\n");
01456   // printf("added_N:    [");
01457   // for (u8 i=0; i < x->num_added_dds; i++) {
01458   //   printf("%d, ", x->counter[i]);
01459   // }
01460   // printf("]\n");
01461 
01462 
01463   for (u8 i=0; i < x->num_old_dds; i++) {
01464     new->N[ndxs_of_old_in_new[i]] = old_N[i];
01465   }
01466   for (u8 i=0; i<x->num_added_dds; i++) {
01467     new->N[ndxs_of_added_in_new[i]] = 0;
01468     for (u8 j=0; j<x->num_added_dds; j++) {
01469       new->N[ndxs_of_added_in_new[i]] += x->Z_inv[i*x->num_added_dds + j] * x->counter[j];
01470       // printf("Z_inv[%u] = %d\n", i*x->num_added_dds + j, x->Z_inv[i*x->num_added_dds + j]);
01471       // printf("x->counter[[%u] = %d\n", j, x->counter[j]);
01472     }
01473   }
01474   // for (u8 i=0; i < x->num_added_dds; i++) {
01475   //   new->N[ndxs_of_added_in_new[i]] = x->counter[i];
01476   // }
01477   // printf("new_N:    [");
01478   // for (u8 i=0; i < x->num_added_dds + x->num_old_dds; i++) {
01479   //   printf("%d, ", new->N[i]);
01480   // }
01481   // printf("]\n\n");
01482 
01483   /* NOTE: new->ll remains the same as elem->ll as p := exp(ll) is invariant under a
01484    * constant multiplicative factor common to all hypotheses. TODO: reference^2 document (currently lives in page 3/5.6/2014 of ian's notebook) */
01485 }
01486 
01487 typedef struct {
01488   u8 num_added_dds;
01489   u8 num_old_dds;
01490   s32 Z_inv[(MAX_CHANNELS-1)*(MAX_CHANNELS-1)];
01491 } recorrelation_params_t;
01492 
01493 void recorrelate_added_sats(void *arg, element_t *elem_)
01494 {
01495   hypothesis_t *elem = (hypothesis_t *) elem_;
01496   recorrelation_params_t *params = (recorrelation_params_t *)arg;
01497 
01498   /* elem->N <- [[I 0] [0 Z_inv]] . elem->N
01499    * where Z_inv is the inverse Lambda reduction matrix having
01500    * shape (num_added_dds, num_added_dds) and I has shape
01501    * (num_old_dds, num_old_dds) */
01502 
01503   s32 recorrelated_N[params->num_added_dds];
01504   memset(recorrelated_N, 0, params->num_added_dds * sizeof(s32));
01505   for (u8 i=0; i<params->num_added_dds; i++) {
01506     for (u8 j=0; j<params->num_added_dds; j++) {
01507       recorrelated_N[i] += params->Z_inv[i*params->num_added_dds + j] * elem->N[params->num_old_dds + j];
01508     }
01509   }
01510   memcpy(&elem->N[params->num_old_dds], recorrelated_N, params->num_added_dds * sizeof(s32));
01511 }
01512 
01513 void print_hyp(void *arg, element_t *elem)
01514 {
01515   u8 num_dds = *( (u8 *) arg );
01516 
01517   hypothesis_t *hyp = (hypothesis_t *)elem;
01518   printf("[");
01519   for (u8 i=0; i< num_dds; i++) {
01520     printf("%"PRId32", ", hyp->N[i]);
01521   }
01522   printf("]: %f\n", hyp->ll);
01523 }
01524 
01525 void add_sats(ambiguity_test_t *amb_test,
01526               u8 ref_prn,
01527               u32 num_added_dds, u8 *added_prns,
01528               s32 *lower_bounds, s32 *upper_bounds,
01529               s32 *Z_inv)
01530 {
01531   /* Make a generator that iterates over the new hypotheses. */
01532   generate_hypothesis_state_t x0;
01533   memcpy(x0.upper_bounds, upper_bounds, num_added_dds * sizeof(s32));
01534   memcpy(x0.lower_bounds, lower_bounds, num_added_dds * sizeof(s32));
01535   memcpy(x0.counter, lower_bounds, num_added_dds * sizeof(s32));
01536   // printf("upper = [");
01537   // for (u8 i=0; i<num_added_dds; i++) {
01538   //   printf("%d, ", x0.upper_bounds[i]);
01539   // }
01540   // printf("]\n");
01541   // printf("lower = [");
01542   // for (u8 i=0; i<num_added_dds; i++) {
01543   //   printf("%d, ", x0.lower_bounds[i]);
01544   // }
01545   // printf("]\n");
01546 
01547   x0.num_added_dds = num_added_dds;
01548   x0.num_old_dds = MAX(1,amb_test->sats.num_sats)-1;
01549 
01550   //then construct the mapping from the old prn indices into the new, and from the added prn indices into the new
01551   u8 i = 0;
01552   u8 j = 0;
01553   u8 k = 0;
01554   u8 old_prns[x0.num_old_dds];
01555   memcpy(old_prns, &amb_test->sats.prns[1], x0.num_old_dds * sizeof(u8));
01556   while (k < x0.num_old_dds + num_added_dds) { //TODO should this be one less, since its just DDs?
01557     if (j == x0.num_added_dds || (old_prns[i] < added_prns[j] && i != x0.num_old_dds)) {
01558       x0.ndxs_of_old_in_new[i] = k;
01559       amb_test->sats.prns[k+1] = old_prns[i];
01560       i++;
01561       k++;
01562     } else if (i == x0.num_old_dds || old_prns[i] > added_prns[j]) {
01563       x0.ndxs_of_added_in_new[j] = k;
01564       amb_test->sats.prns[k+1] = added_prns[j];
01565       j++;
01566       k++;
01567     } else {
01568       printf("This method is being used improperly. This shouldn't happen.\n");
01569       printf("old_prns = [");
01570       for (u8 ii=0; ii < x0.num_old_dds; ii++) {
01571         printf("%d, ",old_prns[ii]);
01572       }
01573       printf("]\n");
01574       printf("added_prns = [");
01575       for (u8 jj=0; jj < x0.num_old_dds; jj++) {
01576         printf("%d, ", added_prns[jj]);
01577       }
01578       printf("]\n");
01579       break;
01580     }
01581   }
01582   amb_test->sats.prns[0] = ref_prn;
01583   amb_test->sats.num_sats = k+1;
01584 
01585   if (x0.num_old_dds == 0 && memory_pool_n_allocated(amb_test->pool) == 0) {
01586     hypothesis_t *empty_element = (hypothesis_t *)memory_pool_add(amb_test->pool); // only in init
01587     /* Start with ll = 0, just for the sake of argument. */
01588     empty_element->ll = 0; // only in init
01589   }
01590 
01591   printf("IAR: %"PRIu32" hypotheses before inclusion\n", memory_pool_n_allocated(amb_test->pool));
01592   if (DEBUG_AMBIGUITY_TEST) {
01593     memory_pool_map(amb_test->pool, &x0.num_old_dds, &print_hyp);
01594   }
01595   memcpy(x0.Z_inv, Z_inv, num_added_dds * num_added_dds * sizeof(s32));
01596   /* Take the product of our current hypothesis state with the generator, recorrelating the new ones as we go. */
01597   memory_pool_product_generator(amb_test->pool, &x0, MAX_HYPOTHESES, sizeof(x0),
01598                                 &generate_next_hypothesis, &hypothesis_prod);
01599   printf("IAR: updates to %"PRIu32"\n", memory_pool_n_allocated(amb_test->pool));
01600   if (DEBUG_AMBIGUITY_TEST) {
01601     memory_pool_map(amb_test->pool, &k, &print_hyp);
01602   }
01603 }
01604 
01605 void init_residual_matrices(residual_mtxs_t *res_mtxs, u8 num_dds, double *DE_mtx, double *obs_cov)
01606 {
01607   res_mtxs->res_dim = num_dds + MAX(3, num_dds) - 3;
01608   res_mtxs->null_space_dim = MAX(3, num_dds) - 3;
01609   assign_phase_obs_null_basis(num_dds, DE_mtx, res_mtxs->null_projector);
01610   assign_residual_covariance_inverse(num_dds, obs_cov, res_mtxs->null_projector, res_mtxs->half_res_cov_inv);
01611   // MAT_PRINTF(res_mtxs->null_projector, res_mtxs->null_space_dim, num_dds);
01612   // MAT_PRINTF(res_mtxs->half_res_cov_inv, res_mtxs->res_dim, res_mtxs->res_dim);
01613 }
01614 
01615 
01616 // void QR_part1(integer m, integer n, double *A, double *tau)
01617 // {
01618 //   double w[1];
01619 //   integer lwork = -1;
01620 //   integer info;
01621 //   integer jpvt[3];
01622 //   memset(jpvt, 0, 3 * sizeof(integer));
01623 //   dgeqp3_(&m, &n,
01624 //           A, &m,
01625 //           jpvt,
01626 //           tau,
01627 //           w, &lwork, &info);
01628 //   lwork = round(w[0]);
01629 //   double work[lwork];
01630 //   dgeqp3_(&m, &n,
01631 //           A, &m,
01632 //           jpvt,
01633 //           tau,
01634 //           work, &lwork, &info); //set A = QR(A)
01635 // }
01636 
01637 // void QR_part2(integer m, integer n, double *A, double *tau)
01638 // {
01639 //   double w[1];
01640 //   integer lwork = -1;
01641 //   integer info;
01642 //   dorgqr_(&m, &m, &n,
01643 //           A, &m,
01644 //           tau,
01645 //           w, &lwork, &info);
01646 //   lwork = round(w[0]);
01647 //   double work[lwork];
01648 //   dorgqr_(&m, &m, &n,
01649 //           A, &m,
01650 //           tau,
01651 //           work, &lwork, &info);
01652 // }
01653 
01654 // void assign_phase_obs_null_basis(u8 num_dds, double *DE_mtx, double *q)
01655 // {
01656 //   // use either GEQRF or GEQP3. GEQP3 is the version with pivoting
01657 //   // int dgeqrf_(__CLPK_integer *m, __CLPK_integer *n, __CLPK_doublereal *a, __CLPK_integer *
01658 //   //       lda, __CLPK_doublereal *tau, __CLPK_doublereal *work, __CLPK_integer *lwork, __CLPK_integer *info)
01659 //   // int dgeqp3_(__CLPK_integer *m, __CLPK_integer *n, __CLPK_doublereal *a, __CLPK_integer *
01660 //   //       lda, __CLPK_integer *jpvt, __CLPK_doublereal *tau, __CLPK_doublereal *work, __CLPK_integer *lwork,
01661 //   //        __CLPK_integer *info)
01662 
01663 //   //DE is num_sats-1 by 3, need to transpose it to column major
01664 //   double A[num_dds * num_dds];
01665 //   for (u8 i=0; i<num_dds; i++) {
01666 //     for (u8 j=0; j<3; j++) {
01667 //       A[j*num_dds + i] = DE_mtx[i*3 + j]; //set A = Transpose(DE_mtx)
01668 //     }
01669 //   }
01670 //   integer m = num_dds;
01671 //   integer n = 3;
01672 //   double tau[3];
01673 //   QR_part1(m, n, A, tau);
01674 //   QR_part2(m, n, A, tau);
01675 //   memcpy(q, &A[3*num_dds], (num_dds-3) * num_dds * sizeof(double));
01676 // }
01677 
01678 void assign_residual_covariance_inverse(u8 num_dds, double *obs_cov, double *q, double *r_cov_inv) //TODO make this more efficient (e.g. via page 3/6.2-3/2014 of ian's notebook)
01679 {
01680   integer dd_dim = 2*num_dds;
01681   integer res_dim = num_dds + MAX(3, num_dds) - 3;
01682   u32 nullspace_dim = MAX(3, num_dds) - 3;
01683   double q_tilde[res_dim * dd_dim];
01684   memset(q_tilde, 0, res_dim * dd_dim * sizeof(double));
01685   // MAT_PRINTF(obs_cov, dd_dim, dd_dim);
01686 
01687   // MAT_PRINTF(q, nullspace_dim, num_dds);
01688   for (u8 i=0; i<nullspace_dim; i++) {
01689     memcpy(&q_tilde[i*dd_dim], &q[i*num_dds], num_dds * sizeof(double));
01690   }
01691   // MAT_PRINTF(q_tilde, res_dim, dd_dim);
01692   for (u8 i=0; i<num_dds; i++) {
01693     q_tilde[(i+nullspace_dim)*dd_dim + i] = 1;
01694     q_tilde[(i+nullspace_dim)*dd_dim + i+num_dds] = -1 / GPS_L1_LAMBDA_NO_VAC;
01695   }
01696   // MAT_PRINTF(q_tilde, res_dim, dd_dim);
01697 
01698   //TODO make more efficient via the structure of q_tilde, and it's relation to the I + 1*1^T structure of the obs cov mtx
01699   double QC[res_dim * dd_dim];
01700   cblas_dsymm(CblasRowMajor, CblasRight, CblasUpper, //CBLAS_ORDER, CBLAS_SIDE, CBLAS_UPLO
01701               res_dim, dd_dim, // int M, int N
01702               1, obs_cov, dd_dim, // double alpha, double *A, int lda
01703               q_tilde, dd_dim, // double *B, int ldb
01704               0, QC, dd_dim); // double beta, double *C, int ldc
01705   // MAT_PRINTF(QC, res_dim, dd_dim);
01706 
01707   //TODO make more efficient via the structure of q_tilde, and it's relation to the I + 1*1^T structure of the obs cov mtx
01708   cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, // CBLAS_ORDER, CBLAS_TRANSPOSE transA, cBLAS_TRANSPOSE transB
01709               res_dim, res_dim, dd_dim, // int M, int N, int K
01710               2, QC, dd_dim, // double alpha, double *A, int lda
01711               q_tilde, dd_dim, //double *B, int ldb
01712               0, r_cov_inv, res_dim); //beta, double *C, int ldc
01713   // MAT_PRINTF(r_cov_inv, res_dim, res_dim);
01714 
01715   // dpotrf_(char *uplo, __CLPK_integer *n, __CLPK_doublereal *a, __CLPK_integer *
01716   //       lda, __CLPK_integer *info)
01717   //dpotri_(char *uplo, __CLPK_integer *n, __CLPK_doublereal *a, __CLPK_integer *
01718   //        lda, __CLPK_integer *info)
01719   char uplo = 'L'; //actually this makes it upper. the lapack stuff is all column major, but we're good since we're operiating on symmetric matrices
01720   integer info;
01721   dpotrf_(&uplo, &res_dim, r_cov_inv, &res_dim, &info);
01722   // printf("info: %i\n", (int) info);
01723   // MAT_PRINTF(r_cov_inv, res_dim, res_dim);
01724   dpotri_(&uplo, &res_dim, r_cov_inv, &res_dim, &info);
01725   for (u8 i=0; i < res_dim; i++) {
01726     for (u8 j=0; j < i; j++) {
01727       r_cov_inv[i*res_dim + j] = r_cov_inv[j*res_dim + i];
01728     }
01729   }
01730   // printf("info: %i\n", (int) info);
01731   // MAT_PRINTF(r_cov_inv, res_dim, res_dim);
01732 }
01733 
01734 void assign_r_vec(residual_mtxs_t *res_mtxs, u8 num_dds, double *dd_measurements, double *r_vec)
01735 {
01736   cblas_dgemv(CblasRowMajor, CblasNoTrans,
01737               res_mtxs->null_space_dim, num_dds,
01738               1, res_mtxs->null_projector, num_dds,
01739               dd_measurements, 1,
01740               0, r_vec, 1);
01741   for (u8 i=0; i< num_dds; i++) {
01742     r_vec[i + res_mtxs->null_space_dim] = dd_measurements[i] - dd_measurements[i+num_dds] / GPS_L1_LAMBDA_NO_VAC;
01743   }
01744 }
01745 
01746 void assign_r_mean(residual_mtxs_t *res_mtxs, u8 num_dds, double *hypothesis, double *r_mean)
01747 {
01748   cblas_dgemv(CblasRowMajor, CblasNoTrans,
01749               res_mtxs->null_space_dim, num_dds,
01750               1, res_mtxs->null_projector, num_dds,
01751               hypothesis, 1,
01752               0, r_mean, 1);
01753   memcpy(&r_mean[res_mtxs->null_space_dim], hypothesis, num_dds * sizeof(double));
01754 }
01755 
01756 double get_quadratic_term(residual_mtxs_t *res_mtxs, u8 num_dds, double *hypothesis, double *r_vec)
01757 {
01758   // VEC_PRINTF(r_vec, res_mtxs->res_dim);
01759   double r[res_mtxs->res_dim];
01760   assign_r_mean(res_mtxs, num_dds, hypothesis, r);
01761   // VEC_PRINTF(r, res_mtxs->res_dim);
01762   for (u32 i=0; i<res_mtxs->res_dim; i++) {
01763     r[i] = r_vec[i] - r[i];
01764   }
01765   // VEC_PRINTF(r, res_mtxs->res_dim);
01766   double half_sig_dot_r[res_mtxs->res_dim];
01767   cblas_dsymv(CblasRowMajor, CblasUpper,
01768                  res_mtxs->res_dim,
01769                  1, res_mtxs->half_res_cov_inv, res_mtxs->res_dim,
01770                  r, 1,
01771                  0, half_sig_dot_r, 1);
01772   // VEC_PRINTF(half_sig_dot_r, res_mtxs->res_dim);
01773   double quad_term = 0;
01774   for (u32 i=0; i<res_mtxs->res_dim; i++) {
01775     quad_term -= half_sig_dot_r[i] * r[i];
01776   }
01777   return quad_term;
01778 }
01779 


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:14