Ejemplo n.º 1
0
/**
 * This function implements the stability criterion of Mardling, 2008a for coplanar,
 * three body systems. 
 * @param alle A matrix of _all_ elements in hierarchical coordinates, as 
 * returned by K_getAllElements_jacobi (or supplied by the user).
 * 
 * @return One of T_INAPPLICABLE, T_STABLE or T_UNSTABLE. The routine returns T_INAPPLICABLE
 * if one of the following is true: (1) the system contains more of three bodies (returns
 * T_STABLE if two-body system); (2) the mass conditions for which n:1 resonances dominate
 * (m_2/m_1 > 0.01 && m_2/m_1 > 0.01 or m_2/m1 > 0.05 || m_3/m_1 > 0.05). The routine returns 
 * T_UNSTABLE if the stability criterion (E_n < 0 and E_(n+1) < 0) is satisfied,
 * T_STABLE otherwise.
 */
int K_isMstable_coplanar(const gsl_matrix* alle) {
    
    if (MROWS(alle) > 3)
        return T_INAPPLICABLE;
    
    if (MROWS(alle) == 2)
        return T_STABLE;
    
    double m_1 = MSUN_TO_MJUP(MGET(alle, 0, MASS));
    double m_2 = MGET(alle, 1, MASS);
    double m_3 = MGET(alle, 2, MASS);
    
    // outside mass criterion
    if ((m_2 / m_1 < 0.01 || m_3 / m_1 < 0.01) && (m_2 / m_1 < 0.05 && m_3 / m_1 < 0.05))
        return T_INAPPLICABLE;
    
    // Elements of inner and outer binary
    double P_i = MGET(alle, 1, PER);
    double P_o = MGET(alle, 2, PER);
    double sigma = P_o/P_i;
    double n = floor(sigma);
    
    double E_n = K_E_n(alle, n, sigma);
    double E_n1 = K_E_n(alle, n+1, sigma);
    
    if (E_n < 0 && E_n1 < 0)
        return T_UNSTABLE;
    else
        return T_STABLE;
}
Ejemplo n.º 2
0
 int multiply_matrix_vector (MATRIX const *m, VECTOR const *v, VECTOR *r)

/*****************************************************************************
 Returns the VECTOR-MATRIX product of m and v in r.
******************************************************************************/
{
  if (! (MV_COMPAT_DIM (*m, *v)))
  {
     printf ("ERROR (multiply_matrix_vector): MATRIX  and VECTOR dimensions incompatible!\n");
     print_matrix ("MATRIX:", m);
     print_vector ("VECTOR:", v);
     return -1; /*added 1996-07*/
  }
  else
  {
    int i, j;
    float datum;

    VELEMENTS (*r) = MROWS (*m);

    for (i = 0; i < MROWS (*m); i++)
    {
        datum = 0;
        for (j = 0; j < VELEMENTS (*v); j++)
            datum = datum + MDATA (*m, i, j) * VDATA (*v, j);
        VDATA (*r, i) = datum;
    }
  }
  return 1;
}
Ejemplo n.º 3
0
int determinant (MATRIX const *m, float *result)
/*****************************************************************************
******************************************************************************/
{
  if (!M_SQUARE (*m))
  {
     printf ("ERROR (determinant): MATRIX must be square!\n");
     print_matrix ("MATRIX:", m);	
	 return -1;     
  }
  else
  {    

    if (MROWS (*m) == 1)
       *result = MDATA (*m, 0, 0);
    else if (MROWS (*m) == 2)
       *result = cross_product (m, 0, 0, 1, 1);
    else
       *result = MDATA (*m, 0, 0) * cross_product (m, 1, 1, 2, 2)
              - MDATA (*m, 0, 1) * cross_product (m, 1, 0, 2, 2)
              + MDATA (*m, 0, 2) * cross_product (m, 1, 0, 2, 1);


    return 1;
  }  
}
Ejemplo n.º 4
0
 int inverse_matrix (MATRIX const *m, MATRIX *n)

/*****************************************************************************
******************************************************************************/
{
  if (!M_SQUARE (*m))
  {	 
     printf ("ERROR (inverse_matrix): MATRIX must be square!\n");
     print_matrix ("MATRIX:", m);
	 n->cols=0; n->rows=0;
     return -1;
  }
  else
  {
    float det;
	int res;

    res = determinant (m,&det);

    if (res == -1)
    {
       printf ("ERROR (inverse_matrix): singular MATRIX!\n");
       print_matrix ("MATRIX:", m);
       return -1;
    }
    else
    {
      initialize_matrix (n, MROWS (*m), MCOLS (*m));
      if (MROWS (*m) == 1)
      {
        MDATA (*n, 0, 0) = 1 / det ;
      }
      else if (MROWS (*m) == 2)
      {
        MDATA (*n, 0, 0) = MDATA (*m, 1, 1) / det ;
        MDATA (*n, 0, 1) = -MDATA (*m, 0, 1) / det ;
        MDATA (*n, 1, 0) = -MDATA (*m, 1, 0) / det ;
        MDATA (*n, 1, 1) = MDATA (*m, 0, 0) / det ;
      }
      else
      {
        MDATA (*n, 0, 0) = cross_product (m, 1, 1, 2, 2) / det ;
        MDATA (*n, 0, 1) = -cross_product (m, 0, 1, 2, 2) / det ;
        MDATA (*n, 0, 2) = cross_product (m, 0, 1, 1, 2) / det ;
        MDATA (*n, 1, 0) = -cross_product (m, 1, 0, 2, 2) / det ;
        MDATA (*n, 1, 1) = cross_product (m, 0, 0, 2, 2) / det ;
        MDATA (*n, 1, 2) = -cross_product (m, 0, 0, 1, 2) / det ;
        MDATA (*n, 2, 0) = cross_product (m, 1, 0, 2, 1) / det ;
        MDATA (*n, 2, 1) = -cross_product (m, 0, 0, 2, 1) / det ;
        MDATA (*n, 2, 2) = cross_product (m, 0, 0, 1, 1) / det ;
      }	  
	}
  }
  return 1;
}
Ejemplo n.º 5
0
/**
 * Get a summary statistic for the orbital elements; for instance,
 * the median value calculated over all the elements of the list.
 * @param kl List
 * @param what Can be one of: STAT_MEAN, STAT_MEDIAN, STAT_STDDEV, STAT_MAD. 
 *      Summary statistic is calculated correctly for angle parameters.
 * @return A matrix whose entries are the summary statistic for the 
 * corresponding orbital element.
 */
gsl_matrix* KL_getElementsStats(const ok_list* kl, const int what) {
    
    int npl = MROWS(kl->kernels[0]->elements);
    if (npl == 0)
        return NULL;
    
    gsl_vector* v = gsl_vector_alloc(kl->size);
    
    gsl_matrix* m = gsl_matrix_alloc(npl, ALL_ELEMENTS_SIZE);
    gsl_matrix_set_all(m, 0.);
    
    
    for (int i = 0; i < npl; i++)
            for (int j = 0; j < ALL_ELEMENTS_SIZE; j++) {
                for (int n = 0; n < kl->size; n++) {
                    VSET(v, n, MGET(kl->kernels[n]->elements, i, j));
                }
                
                switch (what) {
                    case STAT_MEAN:
                        if (j == MA || j == LOP || j == INC || j == NODE || j == TRUEANOMALY)
                            MSET(m, i, j, ok_average_angle(v->data, v->size, false));
                        else
                            MSET(m, i, j, gsl_stats_mean(v->data, 1, v->size));
                        break;
                    case STAT_STDDEV:
                        if (j == MA || j == LOP || j == INC || j == NODE || j == TRUEANOMALY) {
                            MSET(m, i, j, ok_stddev_angle(v->data, v->size, false));
                        }
                        else
                            MSET(m, i, j, gsl_stats_sd(v->data, 1, v->size));
                        break;
                    case STAT_MEDIAN:
                        if (j == MA || j == LOP || j == INC || j == NODE || j == TRUEANOMALY)
                            MSET(m, i, j, ok_median_angle(v->data, v->size, false));
                        else {
                            gsl_sort_vector(v);
                            MSET(m, i, j, gsl_stats_median_from_sorted_data(v->data, 1, v->size));
                        }
                        break;
                    case STAT_MAD:
                        if (j == MA || j == LOP || j == INC || j == NODE || j == TRUEANOMALY) {
                            double med = ok_median_angle(v->data, v->size, false);
                            MSET(m, i, j, 1.4826 * ok_mad_angle(v->data, v->size, med, false));
                        } else {
                            gsl_sort_vector(v);
                            double med = gsl_stats_median_from_sorted_data(v->data, 1, v->size);
                            
                            MSET(m, i, j, 1.4826 * ok_mad(v->data, v->size, med));
                        }
                        break;
                    default:
                        // percentiles
                        gsl_sort_vector(v);
                        MSET(m, i, j, gsl_stats_quantile_from_sorted_data(v->data, 1, v->size, (double)(what)/100.));
                };
            }
    gsl_vector_free(v);
    return m;
}
Ejemplo n.º 6
0
int
M_MatrixResize_SP(void *pA, Uint m, Uint n)
{
	M_MatrixSP *A=pA;
	MROWS(A) = m;
	MCOLS(A) = n;
	/* no resizing of sparse matrices */
	return 0;
}
Ejemplo n.º 7
0
 void initialize_matrix (MATRIX *m, int rows, int cols)

/*****************************************************************************
 Initializes a MATRIX to dimensions (rows, cols) and content zeros.
******************************************************************************/
{
  MROWS (*m) = rows;
  MCOLS (*m) = cols;

  {
    int i, j;

    for (i = 0; i < MROWS (*m); i++)
        for (j = 0; j < MCOLS (*m); j++)
            MDATA (*m, i, j) = 0;
  }

}
Ejemplo n.º 8
0
double K_getRVLine(ok_kernel* k, int row, int col) {
    static gsl_matrix* rvline = NULL;
    static double tolerance[1] = {1e-3};
    static int target_points = 600;

    if (row < 0) {
        int samples = col;
        if (rvline != NULL) {
            gsl_matrix_free(rvline);
            rvline = NULL;
        }
        if (k->ndata == 0)
            return -1;

        double** comp = K_getCompiled(k);

        gsl_matrix* rvline_full = K_integrateStellarVelocity(k, comp[0][0],
                                  comp[k->ndata - 1][0],
                                  samples,
                                  NULL, NULL);
        int fac = 1;

        rvline = ok_resample_curve(rvline_full,
                                   0, 1, 1, target_points, 100, tolerance, 0, false);

        if (MROWS(rvline) > 1.5 * target_points) {
            gsl_matrix_free(rvline);
            rvline = ok_resample_curve(rvline_full,
                                       0, 1, 0.2, target_points, 100, tolerance, 0, false);
            fac = -1;
        }

        gsl_matrix_free(rvline_full);



        return fac * (int) MROWS(rvline);
    } else {
        if (rvline == NULL)
            return INVALID_NUMBER;
        else
            return MGET(rvline, row, col);
    }
}
Ejemplo n.º 9
0
 void print_matrix (char *message, MATRIX const *m)

/*****************************************************************************
 Print to stdout the contents of MATRIX m.
******************************************************************************/
{
  int i, j;

  printf ("%s\n",message);
  printf("%d %d \n",MROWS (*m),MCOLS (*m));
  if ((MROWS (*m) <= MAX_ROWS) && (MCOLS (*m) <= MAX_COLS))
    for (i = 0; i < MROWS (*m); i++)
    {
        for (j = 0; j < MCOLS (*m); j++)
            printf ("%10.5f ", MDATA (*m, i, j));
        printf ("\n");
    }
  else printf ("Dimension incorrecta!");
  printf ("\n");
}
Ejemplo n.º 10
0
 MATRIX create_matrix (int rows, int cols)

/*****************************************************************************
 Creates a MATRIX of dimensions (rows, cols) and initializaes it to zeros.
******************************************************************************/
{
  MATRIX m; 

  MROWS (m) = rows;
  MCOLS (m) = cols;

  {
    int i, j;

    for (i = 0; i < MROWS (m); i++)
        for (j = 0; j < MCOLS (m); j++)
            MDATA (m, i, j) = 0;
  }

  return m;
}
Ejemplo n.º 11
0
void *
M_MatrixNew_SP(Uint m, Uint n)
{
	M_MatrixSP *A;
	int error;

	A = Malloc(sizeof(M_MatrixSP));
	MMATRIX(A)->ops = &mMatOps_SP;
	A->d = spCreate(0, 0, &error);
	MROWS(A) = m;
	MCOLS(A) = n;
	return (A);
}
Ejemplo n.º 12
0
double K_getPhasedRVLine(ok_kernel* k, int planet, int row, int column) {
    static gsl_matrix* phasedRVLine = NULL;
    if (planet >= 1) {
        if (k->ndata == 0)
            return -1;

        int np = K_getNplanets(k);
        double masses[np + 1];
        double periods[np + 1];
        for (int i = 1; i <= np; i++) {
            masses[i] = K_getElement(k, i, MASS);
            periods[i] = K_getElement(k, i, PER);
            if (i != planet) {
                K_setElement(k, i, MASS, 0.);
                K_setElement(k, i, PER, 10000.);
            }
        };

        double period = K_getElement(k, planet, PER);
        int samples = -row;
        if (phasedRVLine != NULL) {
            gsl_matrix_free(phasedRVLine);
            phasedRVLine = NULL;
        }
        double** comp = K_getCompiled(k);

        phasedRVLine = K_integrateStellarVelocity(k, comp[0][0],
                       comp[k->ndata - 1][0],
                       samples,
                       NULL, NULL);

        double mint = MGET(phasedRVLine, 0, T_TIME);
        for (int i = 0; i < MROWS(phasedRVLine); i++) {
            double t = fmod((MGET(phasedRVLine, i, 0) - mint), period);
            MSET(phasedRVLine, i, 0, t);
        }
        ok_sort_matrix(phasedRVLine, 0);

        for (int i = 1; i <= np; i++) {
            K_setElement(k, i, MASS, masses[i]);
            K_setElement(k, i, PER, periods[i]);
        }

        return 1;
    } else {
        return MGET(phasedRVLine, row, column);
    }
}
Ejemplo n.º 13
0
double K_getPhasedDataForPlanet(ok_kernel* k, int planet, int row, int column) {
    static gsl_matrix* phased_data = NULL;

    if (planet >= 1) {
        if (phased_data != NULL) {
            gsl_matrix_free(phased_data);
            phased_data = NULL;
        }
        double chi2 = k->chi2;
        double rms = k->rms;
        double jitter = k->jitter;
        double chi2_rvs = k->chi2_rvs;

        planet = MIN(planet, K_getNplanets(k));
        double mass = K_getElement(k, planet, MASS);
        double period = K_getElement(k, planet, PER);
        K_setElement(k, planet, MASS, 0);
        K_calculate(k);

        phased_data = K_getCompiledDataMatrix(k);
        double mint = MGET(phased_data, 0, T_TIME);
        for (int i = 0; i < MROWS(phased_data); i++) {
            double t = fmod((MGET(phased_data, i, T_TIME) - mint), period);
            double v = MGET(phased_data, i, T_SVAL) - MGET(phased_data, i, T_PRED);
            MSET(phased_data, i, T_TIME, t);
            MSET(phased_data, i, T_VAL, v);
        }

        ok_sort_matrix(phased_data, T_TIME);
        K_setElement(k, planet, MASS, mass);
        K_calculate(k);
        k->chi2 = chi2;
        k->rms = rms;
        k->jitter = jitter;
        k->chi2_rvs = chi2_rvs;
        return 1;
    } else {
        return MGET(phased_data, row, column);
    }
}
Ejemplo n.º 14
0
void KL_fprintf(const ok_list* kl, FILE* out, const char* fmt, const char* lfmt) {
    lfmt = (lfmt != NULL ? lfmt : "%10s%d");
    
    int np = MROWS(kl->kernels[0]->elements)-1;
    int vo = PARAMS_SIZE;
    
    fprintf(out, "# Planets = %d\n", np);
    fprintf(out, "# Trials = %d\n", kl->size);
    fprintf(out, "# Mstar = %e\n", K_getMstar(kl->prototype));
    fprintf(out, "# Epoch = %e\n", K_getEpoch(kl->prototype));
    
    
    
    for (int i = 0; i < ALL_ELEMENTS_SIZE; i++)
        for (int j = 1; j <= np; j++)
            fprintf(out, lfmt, ok_all_orb_labels[i], j);
    for (int i = 0; i < vo; i++)
        fprintf(out, lfmt, "PARAM", i);
    fprintf(out, "\n");
    
    for (int m = 0; m < kl->size; m++) {

        gsl_matrix* ae = kl->kernels[m]->elements;
        for (int i = 0; i < ALL_ELEMENTS_SIZE; i++)
            for (int j = 1; j <= np; j++)
                fprintf(out, fmt, MGET(ae, j, i));
        
        for (int i = 0; i < vo; i++)
            fprintf(out, fmt, VGET(kl->kernels[m]->params, i));
        
        fprintf(out, fmt, kl->kernels[m]->merit);
        fprintf(out, fmt, kl->kernels[m]->merit_pr);
        fprintf(out, fmt, kl->kernels[m]->merit_li);
        fprintf(out, fmt, kl->kernels[m]->tag);
        fprintf(out, " \n");
        
    }
    
}
Ejemplo n.º 15
0
int KL_getNplanets(const ok_list* kl) {
    return MROWS(kl->kernels[0]->elements)-1;
}
Ejemplo n.º 16
0
double K_getPeriodogramAt(ok_kernel* k, int row, int col) {

    static int length;
    static int samples = 15000;
    static double Pmin = 1.;
    static double Pmax = 20000.;
    static ok_periodogram_workspace* p = NULL;
    static gsl_matrix* ps = NULL;
    static const int top_freqs = 10;
    static double* top = NULL;
    static double tolerance[1] = {1e-3};

    if (p == NULL) {
        p = (ok_periodogram_workspace*) malloc(sizeof (ok_periodogram_workspace));
        p->buf = NULL;
        p->per = NULL;
        p->calc_z_fap = true;
    }
    if (row == JS_PS_GET_TOP_PERIODS) {
        return top[col];
    } else if (row == JS_PS_GET_TOP_POWERS) {
        return top[col + top_freqs];
    } else if (row == JS_PS_GET_TOP_FAPS) {
        return top[col + 2 * top_freqs];
    } else if (row == JS_PS_SET_PMIN) {
        Pmin = (double) col;
        return 0;
    } else if (row == JS_PS_SET_PMAX) {
        Pmax = (double) col;
        return 0;
    } else if (row == JS_PS_SETUP) {
        if (ps != NULL) {
            gsl_matrix_free(ps);
            ps = NULL;
        }
        if (top == NULL)
            top = (double*) malloc(top_freqs * 3 * sizeof (double));
        gsl_matrix* data = K_getCompiledDataMatrix(k);
        for (int i = 0; i < MROWS(data); i++)
            MSET(data, i, T_SVAL, MGET(data, i, T_SVAL) - MGET(data, i, T_PRED));

        gsl_matrix* ret = ok_periodogram_ls(data, samples, Pmin, Pmax,
                                            0, T_TIME, T_SVAL, T_ERR, p);

        ps = ok_resample_curve(ret, 0, 1, 0.1, 800,
                               100, tolerance, 0, true);
        length = MROWS(ps);

        ok_sort_matrix(ret, PS_Z);
        double dt = 0.5;
        int idx = MROWS(ret);
        int i = 0;
        while (idx > 0 && i < top_freqs) {
            idx--;
            bool skip = false;
            for (int n = 0; n < i; n++)
                if (fabs(top[n] - MGET(ret, idx, PS_TIME)) < dt)
                    skip = true;

            if (!skip) {
                top[i] = MGET(ret, idx, PS_TIME);
                top[i + top_freqs] = MGET(ret, idx, PS_Z);
                top[i + 2 * top_freqs] = MGET(ret, idx, PS_FAP);
                i++;
            }
        }
        gsl_matrix_free(data);

        return (double) length;
    } else if (row == JS_PS_GET_FAPS_LEVELS) {
        if (p == NULL || ps == NULL)
            return 0;
        if (col == 1)
            return p->z_fap_1;
        else if (col == 2)
            return p->z_fap_2;
        else if (col == 3)
            return p->z_fap_3;
        else
            return 0.;
    } else {
        if (ps == NULL)
            return 0;
        return MGET(ps, row, col);
    }
}
Ejemplo n.º 17
0
/**
 * Computes the Lomb-Scargle periodogram of the matrix "data". "data" should contain at least three
 * columns: time, measurement and measurement error. The periodogram is calculated in "samples" intervals
 * between "Pmin" and "Pmax", spaced logarithmically. 
 * 
 * The function returns a matrix of "samples" rows and several columns, including period, power (z) and 
 * an estimation of the upper bound for the false alarm probability. The estimation is calculated using 
 * the method of Baluev, 2008 (Baluev08). The column PS_Z_LS contains the unnormalized LS periodogram 
 * (z = 1/2 * (Chi^2_0 - Chi^2_SC)), while the column PS_Z contains z_1 = 1/2 * N_H * z / Chi^2_0 (z_1 in Baluev08). 
 * The FAP upper bound is estimated as ~ tau(z_1). (Another estimate of the FAP can be calculated by 
 * estimating the indep. frequencies through your own algorithm, or using the ok_periodogram_boot routine.)
 * 
 * @param data Input data containing the data; each row containing (t_i, x_i, sigma_i)
 * @param samples Number of frequencies sampled
 * @param Pmin Minimum period sampled
 * @param Pmax Maximum period sampled
 * @param method Method to compute periodogram (ignored)
 * @param timecol Time column (e.g. 0) in the matrix data
 * @param valcol Value column (e.g. 1) in the matrix data
 * @param sigmacol Sigma column (e.g. 2) in the matrix data
 * @param p If not NULL, it is used to return additional info for the periodogram and reuse matrices to save space/speed. If you pass
 * a value different than NULL, you are responsible for deallocating the workspace and its fields. p->buf is an array of
 * gsl_matrix*, sized the same as the value of omp_get_max_threads().
 * @return A matrix containing: {PS_TIME, PS_Z, PS_FAP, PS_Z_LS} (period, power, FAP upper limit, unnormalized
 * LS power). You are responsible for deallocating it.
 */
gsl_matrix* ok_periodogram_ls(const gsl_matrix* data, const unsigned int samples, const double Pmin, const double Pmax, const int method,
                              unsigned int timecol, unsigned int valcol, unsigned int sigcol, ok_periodogram_workspace* p) {

    gsl_matrix* ret = NULL;
    gsl_matrix* buf = NULL;
    gsl_vector* bufv = gsl_vector_alloc(data->size1);

    int ndata = data->size1;

    // If no pre-allocated buffers are passed through p, or p is null,
    // allocate those buffers.
    if (p != NULL) {
        if (p->per != NULL && MROWS(p->per) == samples && MCOLS(p->per) == PS_SIZE)
            ret = p->per;
        if (p->buf != NULL && MROWS(p->buf) == ndata && MCOLS(p->per) == 5)
            ret = p->buf;
    }

    ret = (ret != NULL ? ret : gsl_matrix_alloc(samples, PS_SIZE));
    buf = (buf != NULL ? buf : gsl_matrix_alloc(ndata, 5));

    double fmin = 1. / Pmax;
    double fmax = 1. / Pmin;
    double df = (fmax - fmin) / (double) samples;


    gsl_matrix_get_col(bufv, data, timecol);
    double W = 2. * M_PI * gsl_stats_sd(bufv->data, 1, ndata) / Pmin;
    gsl_matrix_get_col(bufv, data, valcol);
    double avg = gsl_stats_mean(bufv->data, 1, ndata);
    double z1_max = 0.;
    double xa[ndata];

    // pre-calculate cdf, sdf
    for (int i = 0; i < ndata; i++) {
        double t = MGET(data, i, timecol) - MGET(data, 0, timecol);
        MSET(buf, i, BUF_CDF, cos(2 * M_PI * df * t));
        MSET(buf, i, BUF_SDF, sin(2 * M_PI * df * t));
        MSET(buf, i, BUF_C, cos(2 * M_PI * fmin * t));
        MSET(buf, i, BUF_S, sin(2 * M_PI * fmin * t));
        MSET(buf, i, BUF_SIG, 1. / (MGET(data, i, sigcol) * MGET(data, i, sigcol)));
        xa[i] = MGET(data, i, valcol) - avg;
    }

    // Calculate periodogram by looping over all angular frequencies
    for (int i = 0; i < samples; i++) {
        // Current frequency
        double f = fmin + df * i;


        double w = 2 * M_PI*f;

        // Calculate tau(w)
        double s_2wt = 0.;
        double c_2wt = 0.;

        for (int j = 0; j < ndata; j++) {
            double cos_wt = C(j);
            double sin_wt = S(j);
            c_2wt += (1. - 2. * sin_wt * sin_wt) * SIG(j);
            s_2wt += (2. * sin_wt * cos_wt) * SIG(j);
        }

        double tau = atan2(s_2wt, c_2wt) / (2. * w);
        double numa = 0.;
        double numb = 0.;
        double dena = 0.;
        double denb = 0.;
        double numa_w = 0.;
        double numb_w = 0.;
        double dena_w = 0.;
        double denb_w = 0.;

        double coswtau = cos(w * tau);
        double sinwtau = sin(w * tau);
        double chi2_h = 0.;
        double chi2_h_w = 0;

        for (int j = 0; j < ndata; j++) {

            double sig = SIG(j);

            const double cos_wt = C(j);
            const double sin_wt = S(j);

            double cos_wdf = CDF(j);
            double sin_wdf = SDF(j);

            double c = cos_wt * coswtau + sin_wt * sinwtau;
            double s = sin_wt * coswtau - cos_wt * sinwtau;
            double x = xa[j];

            MSET(buf, j, BUF_C, cos_wt * cos_wdf - sin_wt * sin_wdf);
            MSET(buf, j, BUF_S, sin_wt * cos_wdf + cos_wt * sin_wdf);

            numa += x * c * sig;
            numb += x * s * sig;
            dena += c * c * sig;
            denb += s * s * sig;
            chi2_h += x * x * sig;

            numa_w += c;
            numb_w += s;
            dena_w += c*c;
            denb_w += s*s;

            chi2_h_w += 1;
        }


        double z = 0.5 * (numa * numa / dena + numb * numb / denb);
        double z_1 = z * ndata / chi2_h;

        double w_1 = 0.5 * (numa_w * numa_w / dena_w + numb_w * numb_w / denb_w) * ndata / chi2_h_w;

        double fap_single = pow(1. - 2. * z_1 / (double) ndata, 0.5 * (double) (ndata - 3.));
        double tau_z = W * fap_single * sqrt(z_1);

        MSET(ret, samples - i - 1, PS_TIME, 1. / f);
        MSET(ret, samples - i - 1, PS_Z, z_1);
        MSET(ret, samples - i - 1, PS_Z_LS, z);
        MSET(ret, samples - i - 1, PS_FAP, MIN(fap_single + tau_z, 1.));
        MSET(ret, samples - i - 1, PS_TAU, tau);
        MSET(ret, samples - i - 1, PS_WIN, w_1);

        z1_max = MAX(z1_max, z_1);
    }

    if (p != NULL && p->calc_z_fap) {
        gsl_root_fsolver * s = gsl_root_fsolver_alloc(gsl_root_fsolver_brent);
        double pars[3];
        pars[0] = ndata;
        pars[1] = W;
        pars[2] = 0.;

        gsl_function F;
        F.function = _baluev_tau;
        F.params = pars;

        double zz = z1_max;
        while (_baluev_tau(zz, pars) > 1e-3)
            zz *= 2;

        p->z_fap_3 = _find_z(s, &F, 1e-3, 0.1, zz);
        p->z_fap_2 = _find_z(s, &F, 1e-2, 0.1, p->z_fap_3);
        p->z_fap_1 = _find_z(s, &F, 1e-1, 0.1, p->z_fap_2);


        gsl_root_fsolver_free(s);
        p->calc_z_fap = false;
    }

    if (p == NULL) {
        gsl_matrix_free(buf);
    } else {
        p->per = ret;
        p->buf = buf;
        p->zmax = z1_max;
    };

    gsl_vector_free(bufv);

    return ret;
}