/** * @brief Compute Aberth correction for j-th root, without * selective correction. */ void mps_daberth (mps_context * s, mps_approximation * root, cdpe_t abcorr) { int i; cdpe_t z; cdpe_set (abcorr, cdpe_zero); for (i = 0; i < s->n; i++) { if (s->root[i] == root) continue; cdpe_sub (z, root->dvalue, s->root[i]->dvalue); cdpe_inv_eq (z); cdpe_add_eq (abcorr, z); } }
/** * @brief Compute Aberth correction for the j-th root, * but only with other roots of the <code>jc</code>-th * cluster. */ void mps_daberth_s (mps_context * s, mps_approximation * ab_root, mps_cluster * cluster, cdpe_t abcorr) { mps_root * root; cdpe_t z; cdpe_set (abcorr, cdpe_zero); for (root = cluster->first; root != NULL; root = root->next) { mps_approximation * appr = s->root[root->k]; if (appr == ab_root) continue; cdpe_sub (z, ab_root->dvalue, appr->dvalue); cdpe_inv_eq (z); cdpe_add_eq (abcorr, z); } }
void mps_daberth_wl (mps_context * s, int j, cdpe_t abcorr, pthread_mutex_t * aberth_mutexes) { int i; cdpe_t z, droot; pthread_mutex_lock (&aberth_mutexes[j]); cdpe_set (droot, s->root[j]->dvalue); pthread_mutex_unlock (&aberth_mutexes[j]); cdpe_set (abcorr, cdpe_zero); for (i = 0; i < s->n; i++) { if (i == j) continue; pthread_mutex_lock (&aberth_mutexes[i]); cdpe_sub (z, droot, s->root[i]->dvalue); pthread_mutex_unlock (&aberth_mutexes[i]); cdpe_inv_eq (z); cdpe_add_eq (abcorr, z); } }
/** * @brief Multithread worker for mps_thread_dpolzer () */ static void * mps_thread_dpolzer_worker (void *data_ptr) { int iter, i; rdpe_t rad1, rtmp; cdpe_t corr, abcorr; /* Parse input data */ mps_thread_worker_data *data = (mps_thread_worker_data*)data_ptr; mps_context *s = data->s; mps_polynomial *p = s->active_poly; mps_thread_job job; while (!(*data->excep) && (*data->nzeros < data->required_zeros)) { job = mps_thread_job_queue_next (s, data->queue); i = job.i; iter = job.iter; /* Check if we got over the maximum number of iterations */ if (job.iter == MPS_THREAD_JOB_EXCEP) { (*data->excep) = true; return 0; } /* Make sure that we are the only one iterating on this root */ if (s->pool->n > 1) pthread_mutex_lock (&data->roots_mutex[i]); if (s->root[i]->again) { /* Check if, while we were waiting, excep condition has been reached */ if (*data->excep || !s->root[i]->again || (*data->nzeros > data->required_zeros)) { if (s->pool->n > 1) pthread_mutex_unlock (&data->roots_mutex[i]); return 0; } (*data->it)++; rdpe_set (rad1, s->root[i]->drad); mps_polynomial_dnewton (s, p, s->root[i], corr); if (iter == 0 && !s->root[i]->again && rdpe_gt (s->root[i]->drad, rad1) && rdpe_ne (rad1, rdpe_zero)) rdpe_set (s->root[i]->drad, rad1); /************************************************ The above condition is needed to manage with the case where at the first iteration the starting point is already in the root neighbourhood and the actually computed radius is too big since the value of the first derivative is too small. In this case the previous radius bound, obtained by means of Rouche' is more reliable and strict **********************************************/ if (s->root[i]->again /* the correction is performed only if iter!=1 or rad(i)!=rad1 */ || iter != 0 || rdpe_ne (s->root[i]->drad, rad1)) { mps_daberth (s, s->root[i], abcorr); cdpe_mul_eq (abcorr, corr); cdpe_sub (abcorr, cdpe_one, abcorr); if (cdpe_eq_zero (abcorr)) { MPS_DEBUG (s, "Aberth correction is zero."); s->lastphase = dpe_phase; cdpe_set_d (abcorr, DBL_EPSILON, 0); } cdpe_div (abcorr, corr, abcorr); cdpe_sub_eq (s->root[i]->dvalue, abcorr); cdpe_mod (rtmp, abcorr); rdpe_add_eq (s->root[i]->drad, rtmp); } /* check for new approximated roots */ if (!s->root[i]->again) { (*data->nzeros)++; if ((*data->nzeros) >= data->required_zeros) { if (s->pool->n > 1) pthread_mutex_unlock (&data->roots_mutex[i]); return 0; } } } if (s->pool->n > 1) pthread_mutex_unlock (&data->roots_mutex[i]); } return NULL; }