BiquadPoleState::BiquadPoleState (const BiquadBase& s) { const double a0 = s.getA0 (); const double a1 = s.getA1 (); const double a2 = s.getA2 (); const double b0 = s.getB0 (); const double b1 = s.getB1 (); const double b2 = s.getB2 (); if (a2 == 0 && b2 == 0) { // single pole poles.first = -a1; zeros.first = -b0 / b1; poles.second = 0; zeros.second = 0; } else { { const complex_t c = sqrt (complex_t (a1 * a1 - 4 * a0 * a2, 0)); double d = 2. * a0; poles.first = -(a1 + c) / d; poles.second = (c - a1) / d; assert (!poles.is_nan()); } { const complex_t c = sqrt (complex_t ( b1 * b1 - 4 * b0 * b2, 0)); double d = 2. * b0; zeros.first = -(b1 + c) / d; zeros.second = (c - b1) / d; assert (!zeros.is_nan()); } } gain = b0 / a0; }
void RootFinderBase::solve (int degree, bool polish, bool doSort) { assert (degree <= m_maxdegree); const double EPS = 1.0e-30; int its; complex_t x, b, c; int m = degree; // copy coefficients for (int j = 0; j <= m; ++j) m_ad[j] = m_a[j]; // for each root for (int j = m - 1; j >= 0; --j) { // initial guess at 0 x = 0.0; laguerre (j + 1, m_ad, x, its); if (fabs (std::imag(x)) <= 2.0 * EPS * fabs (std::real(x))) x = complex_t (std::real(x), 0.0); m_root[j] = x; // deflate b = m_ad[j+1]; for (int jj = j; jj >= 0; --jj) { c = m_ad[jj]; m_ad[jj] = b; b = x * b + c; } } if (polish) for (int j = 0; j < m; ++j) laguerre (degree, m_a, m_root[j], its); if (doSort) sort (degree); }
complex_vec_t fourier_transform::forwards(const complex_vec_t &in) const { size_t n=calc_padded_size(in.size()); complex_vec_t result(n); complex_t wn=root_of_unity(n); if(n==in.size()){ forwards_impl(n, wn, &in[0], 1, &result[0], 1); }else{ complex_vec_t buffer(in); buffer.resize(n, complex_t(0.0,0.0) ); forwards_impl(n, wn, &buffer[0], 1, &result[0], 1); } return result; }
void fourierCoeff(std::size_t precision, std::size_t summands, const real_t& tMax, const real_t& sigma, const lapFunc_t& f, const real_t& errorExponentFactor, std::vector<complex_t>& funcEvals, std::vector<real_t>& errorEval) { const real_t T = tMax / real_t(2) * real_t("1.01"); #pragma omp parallel { casema::Constants<real_t>::init(precision); const real_t zero(0); #pragma omp for schedule(static) for (std::size_t k = 1; k <= summands; ++k) { const real_t kpit = k * casema::Constants<real_t>::pi() / T; funcEvals[k-1] = f.withoutInlet(sigma + complex_t(zero, kpit)); errorEval[k-1] -= sqrt(real_t(k)) * errorExponentFactor; } casema::Constants<real_t>::clear(); } }
std::vector<complex_t> createSampleCoefficients(const ShapeEnum<D,MultiIndex>& enumeration) { std::vector<complex_t> coeffs(enumeration.n_entries()); real_t norm = 0.0; std::size_t ordinal = 0; for (int islice = 0; islice < enumeration.n_slices(); islice++) { for (auto index : enumeration.slice(islice)) { real_t falloff = 0.1; real_t x = 0.0; real_t y = 0.0; int sum = 0; for (dim_t d = 0; d < D; d++) { x += std::sin(index[d] + 1.0*(d+1)/real_t(D)); y += std::cos(index[d] + 1.5*(d+1)/real_t(D)); sum += index[d]; } x *= std::exp(-falloff*sum); y *= std::exp(-falloff*sum); coeffs[ordinal] = complex_t(x,y); //std::cout << index << ": " << coeffs[ordinal] << std::endl; norm += x*x + y*y; ordinal++; } } //normalize wavepacket for (auto & c : coeffs) c /= norm; return coeffs; }
virtual void forwards_impl( size_t n, const std::complex<double> &/*wn*/, const std::complex<double> *pIn, size_t sIn, std::complex<double> *pOut, size_t sOut ) const { assert(n>0); const double PI=3.1415926535897932384626433832795; // = -i*2*pi / n complex_t neg_im_2pi_n=-complex_t(0.0, 1.0)*2.0*PI / (double)n; tbb::parallel_for((unsigned) 0 , (unsigned)n, [=](unsigned kk){ complex_t acc=0; for(size_t ii=0;ii<n;ii++){ // acc += exp(-i * 2 * pi * kk / n); acc+=pIn[ii*sIn] * exp( neg_im_2pi_n * (double)kk * (double)ii ); } pOut[kk*sOut]=acc; } ); }
std::complex<double> fourier_transform::root_of_unity(size_t n) const { const double pi2=6.283185307179586476925286766559; double angle = pi2/n; return complex_t(cos(angle), sin(angle)); }
/** * Check the compatibility relations * \f[\begin{align} * Q^{\texttt{H}} P - P^{\texttt{H}} Q & = 2i I \\ * Q^{\texttt{T}} P - P^{\texttt{T}} Q & = 0 * \end{align}\f] */ bool compatible() const { const double tol = 1e-10; CMatrix<D,D> C1 = Q_.adjoint()*P_ - P_.adjoint()*Q_ - CMatrix<D,D>::Identity()*complex_t(0,2); CMatrix<D,D> C2 = Q_.transpose()*P_ - P_.transpose()*Q_; return C1.template lpNorm<1>() < tol && C2.template lpNorm<1>() < tol; }
/** * Computational kernel function. */ inline complex_t NumericFormFactorC::compute_fq(real_t s, complex_t qt, complex_t qn) { complex_t v1 = qn * complex_t(cos(qt.real()), sin(qt.real())); real_t v2 = s * exp(qt.imag()); return v1 * v2; } // NumericFormFactorC::compute_fq()
/** * prism - 3 face */ bool AnalyticFormFactor::compute_prism(shape_param_list_t& params, std::vector<complex_t>& ff, real_t tau, real_t eta, vector3_t transvec) { std::vector<real_t> l, distr_l; std::vector<real_t> h, distr_h; for(shape_param_iterator_t i = params.begin(); i != params.end(); ++ i) { switch((*i).second.type()) { case param_edge: param_distribution((*i).second, l, distr_l); break; case param_height: param_distribution((*i).second, h, distr_h); break; case param_xsize: case param_ysize: case param_radius: case param_baseangle: std::cerr << "warning: ignoring unwanted parameters in prism" << std::endl; break; default: std::cerr << "error: invalid parameter given for prism" << std::endl; return false; } // switch } // for if(h.size() < 1 || l.size() < 1) { std::cerr << "error: need edge and height for prism shape" << std::endl; return false; } // if // why not doing for a range of r, h for this? ... ??? #ifdef TIME_DETAIL_2 woo::BoostChronoTimer maintimer; maintimer.start(); #endif // TIME_DETAIL_2 #ifdef FF_ANA_GPU // on gpu #ifdef FF_VERBOSE std::cout << "-- Computing prism3 FF on GPU ..." << std::endl; #endif std::vector<real_t> transvec_v; transvec_v.push_back(transvec[0]); transvec_v.push_back(transvec[1]); transvec_v.push_back(transvec[2]); gff_.compute_prism3(tau, eta, l, distr_l, h, distr_h, rot_, transvec_v, ff); #else // on cpu std::cout << "-- Computing prism3 FF on CPU ..." << std::endl; real_t sqrt3 = sqrt(3.0); complex_t unitc(0, 1.0); ff.clear(); ff.resize(nqz_, CMPLX_ZERO_); #pragma omp parallel for for(unsigned int z = 0; z < nqz_; ++ z) { unsigned int y = z % nqy_; std::vector<complex_t> mq = rot_.rotate(QGrid::instance().qx(y), QGrid::instance().qy(y), QGrid::instance().qz_extended(z)); complex_t mqx = mq[0]; complex_t mqy = mq[1]; complex_t mqz = mq[2]; complex_t temp1 = mqx * (mqx * mqx - 3.0 * mqy * mqy); complex_t temp2 = mqz + tan(tau) * (mqx * sin(eta) + mqy * cos(eta)); complex_t temp_ff(0.0, 0.0); for(unsigned int i_l = 0; i_l < l.size(); ++ i_l) { for(unsigned int i_h = 0; i_h < h.size(); ++ i_h) { complex_t temp4 = mqx * exp(unitc * mqy * l[i_l] * sqrt3); complex_t temp5 = mqx * cos(mqx * l[i_l]); complex_t temp6 = unitc * sqrt3 * mqy * sin(mqx * l[i_l]); complex_t temp7 = fq_inv(temp2, h[i_h]); complex_t temp8 = (temp4 - temp5 - temp6) * temp7; complex_t temp3 = mqy * l[i_l] / sqrt3; complex_t temp9 = 2.0 * sqrt3 * exp(complex_t(temp3.imag(), -temp3.real())); temp_ff += (temp9 / temp1) * temp8; } // for h } // for r complex_t temp10 = mqx * transvec[0] + mqy * transvec[1] + mqz * transvec[2]; ff[z] = temp_ff * exp(complex_t(-temp10.imag(), temp10.real())); } // for z #endif // FF_ANA_GPU #ifdef TIME_DETAIL_2 maintimer.stop(); std::cout << "** Prism3 FF compute time: " << maintimer.elapsed_msec() << " ms." << std::endl; #endif // TIME_DETAIL_2 return true; } // AnalyticFormFactor::compute_prism()
/** * Function to gather partial FF arrays from all processes to construct the final FF. * This is a bottleneck for large num procs ... */ bool NumericFormFactor::construct_ff(int p_nqx, int p_nqy, int p_nqz, int nqx, int nqy, int nqz, int p_y, int p_z, #ifdef FF_NUM_GPU cucomplex_t* p_ff, #else complex_t* p_ff, #endif complex_vec_t& ff, #ifdef USE_MPI woo::MultiNode& world_comm, std::string comm_key, #endif real_t& mem_time, real_t& comm_time) { real_t mem_start = 0, mem_end = 0, comm_start = 0, comm_end = 0; woo::BoostChronoTimer memtimer, commtimer; mem_time = 0; comm_time = 0; #ifdef USE_MPI bool master = world_comm.is_master(comm_key); int size = world_comm.size(comm_key); int rank = world_comm.rank(comm_key); #else bool master = true; int size = 1; int rank = 0; #endif memtimer.start(); int local_qpoints = p_nqx * p_nqy * p_nqz; unsigned long int total_qpoints = nqx * nqy * nqz; // process 0 creates the main ff, and collects computed p_ff from all others (just use gather) ff.clear(); #ifdef FF_NUM_GPU cucomplex_t* all_ff = NULL; // TODO: improve this ... #else complex_t* all_ff = NULL; #endif if(master) { ff.reserve(total_qpoints); ff.assign(total_qpoints, complex_t(0.0, 0.0)); #ifdef FF_NUM_GPU all_ff = new (std::nothrow) cucomplex_t[total_qpoints]; #else all_ff = new (std::nothrow) complex_t[total_qpoints]; #endif } // if mem_time += memtimer.elapsed_msec(); int *recv_p_nqy = new (std::nothrow) int[p_y](); recv_p_nqy[0] = p_nqy; int *off_p_nqy = new (std::nothrow) int[p_y](); off_p_nqy[0] = 0; #ifdef FF_NUM_GPU cucomplex_t *ff_buffer = new (std::nothrow) cucomplex_t[total_qpoints]; #else complex_t *ff_buffer = new (std::nothrow) complex_t[total_qpoints]; #endif if(ff_buffer == NULL) { std::cerr << "error: failed to allocate memory for ff buffer" << std::endl; return false; } // if #ifdef USE_MPI // construct stuff for gatherv int *recv_counts = new (std::nothrow) int[size](); int *displs = new (std::nothrow) int[size](); commtimer.start(); //comm.Allgather(&local_qpoints, 1, MPI::INT, recv_counts, 1, MPI::INT); world_comm.allgather(comm_key, &local_qpoints, 1, recv_counts, 1); commtimer.stop(); comm_time += commtimer.elapsed_msec(); memtimer.start(); displs[0] = 0; for(int i = 1; i < size; ++ i) { displs[i] = displs[i - 1] + recv_counts[i - 1]; } // for complex_t *cast_p_ff, *cast_ff; #ifdef FF_NUM_GPU cast_p_ff = reinterpret_cast<complex_t*>(p_ff); cast_ff = reinterpret_cast<complex_t*>(ff_buffer); #else cast_p_ff = p_ff; cast_ff = ff_buffer; #endif memtimer.stop(); mem_time += memtimer.elapsed_msec(); commtimer.start(); world_comm.gatherv(comm_key, cast_p_ff, local_qpoints, cast_ff, recv_counts, displs); world_comm.gather("ff_num_col_comm", &p_nqy, 1, recv_p_nqy, 1); commtimer.stop(); comm_time += commtimer.elapsed_msec(); for(int i = 1; i < p_y; ++ i) off_p_nqy[i] = off_p_nqy[i - 1] + recv_p_nqy[i - 1]; #else #ifdef FF_NUM_GPU memcpy(ff_buffer, p_ff, total_qpoints * sizeof(cucomplex_t)); #else memcpy(ff_buffer, p_ff, total_qpoints * sizeof(complex_t)); #endif #endif // USE_MPI memtimer.start(); // move all the data to correct places if(rank == 0) { unsigned long int ff_index = 0; for(int i_nqz = 0; i_nqz < nqz; ++ i_nqz) { for(int i_py = 0; i_py < p_y; ++ i_py) { unsigned long int ffb_index = nqx * (i_nqz * recv_p_nqy[i_py] + nqz * off_p_nqy[i_py]); #ifdef FF_NUM_GPU memcpy(&all_ff[ff_index], &ff_buffer[ffb_index], nqx * recv_p_nqy[i_py] * sizeof(cucomplex_t)); #else memcpy(&all_ff[ff_index], &ff_buffer[ffb_index], nqx * recv_p_nqy[i_py] * sizeof(complex_t)); #endif ff_index += nqx * recv_p_nqy[i_py]; } // for i_py } // for i_nqz // put into the final ff buffer #ifdef FF_NUM_GPU ff.assign(reinterpret_cast<complex_t*>(all_ff), reinterpret_cast<complex_t*>(all_ff + total_qpoints)); #else ff.assign(all_ff, all_ff + total_qpoints); #endif } // if delete[] ff_buffer; #ifdef USE_MPI delete[] displs; delete[] recv_counts; #endif delete[] off_p_nqy; delete[] recv_p_nqy; delete[] all_ff; memtimer.stop(); mem_time += memtimer.elapsed_msec(); return true; } // NumericFormFactor::construct_ff()
bool NumericFormFactor::compute2(const char * filename, complex_vec_t &ff, RotMatrix_t & rot #ifdef USE_MPI , woo::MultiNode & world_comm, std::string comm_key #endif ) { // initialize init (rot, ff); // read file std::vector<vertex_t> vertices; std::vector<std::vector<int>> faces; std::vector<std::vector<int>> dummy; ObjectShapeReader shape_reader; if (!shape_reader.load_object (filename, vertices, faces, dummy)) { std::cerr << "Error: shape reader failed to load triangles" << std::endl; return false; } // create triangles int num_triangles = faces.size(); triangle_t * triangles = new (std::nothrow) triangle_t [num_triangles]; for (int i = 0; i < num_triangles; i++) { triangles[i].v1[0] = vertices[faces[i][0]-1].x; triangles[i].v1[1] = vertices[faces[i][0]-1].y; triangles[i].v1[2] = vertices[faces[i][0]-1].z; triangles[i].v2[0] = vertices[faces[i][1]-1].x; triangles[i].v2[1] = vertices[faces[i][1]-1].y; triangles[i].v2[2] = vertices[faces[i][1]-1].z; triangles[i].v3[0] = vertices[faces[i][2]-1].x; triangles[i].v3[1] = vertices[faces[i][2]-1].y; triangles[i].v3[2] = vertices[faces[i][2]-1].z; } //#ifndef __SSE3__ real_vec_t shape_def; //#else //#ifdef USE_GPU // real_vec_t shape_def; //#else // real_t * shape_def = NULL; //#endif //#endif //unsigned int num_triangles = read_shapes_file(filename, shape_def); #ifdef USE_MPI int num_procs = world_comm.size(comm_key); int rank = world_comm.rank(comm_key); bool master = world_comm.is_master(comm_key); #else bool master = true; #endif if(master) { std::cout << "-- Numerical form factor computation ..." << std::endl << "** Using input shape file: " << filename << std::endl << "** Number of input triangles: " << num_triangles << std::endl << "** Q-grid resolution (q-points): " << nqy_ << std::endl #ifdef USE_MPI << "** Number of processes requested: " << num_procs << std::endl #endif << std::flush; } // if // copy q-points real_t * qx = new (std::nothrow) real_t [nqy_]; if (qx == NULL) { std::cerr << "Error: failure in allocation memeroy." << std::endl; return false; } for (int i = 0; i < nqy_; i++ ) qx[i] = QGrid::instance().qx(i); real_t * qy = new (std::nothrow) real_t [nqy_]; if (qy == NULL) { std::cerr << "Error: failure in allocation memeroy." << std::endl; return false; } for (int i = 0; i < nqy_; i++) qy[i] = QGrid::instance().qy(i); #ifdef FF_NUM_GPU cucomplex_t * qz = new (std::nothrow) cucomplex_t [nqz_]; if (qz == NULL) { std::cerr << "Error: failure in memeroy allocation." << std::endl; return 0; } for (int i = 0; i < nqz_; i++) { qz[i].x = QGrid::instance().qz_extended(i).real(); qz[i].y = QGrid::instance().qz_extended(i).imag(); } #else complex_t * qz = new (std::nothrow) complex_t [nqz_]; if (qz == NULL) { std::cerr << "Error: failure in memeroy allocation." << std::endl; return 0; } for (int i = 0; i < nqz_; i++) qz[i] = QGrid::instance().qz_extended(i); #endif real_t compute_time = 0.; #ifdef FF_NUM_GPU cucomplex_t * p_ff = NULL; // call kernel if (num_triangles != gff_.compute_exact_triangle(triangles, num_triangles, p_ff, nqy_, qx, qy, nqz_, qz, rot_, compute_time)) { std::cerr << "Calculation of numerical form-factor failed" << std::endl; return false; } for (int i = 0; i < nqz_; i++) ff.push_back (complex_t(p_ff[i].x, p_ff[i].y)); std::cout << "** FF GPU compute time: " << compute_time << " ms." << std::endl; #else complex_t * p_ff = new (std::nothrow) complex_t[nqz_]; if (p_ff == NULL){ std::cerr << "Error: failed to allocate memory of size: " << nqz_ * sizeof(complex_t) << std::endl; return false; } if (num_triangles != cff_.compute_exact_triangle(triangles, num_triangles, p_ff, nqy_, qx, qy, nqz_, qz, rot_, compute_time)) { std::cerr << "Calculation of numerical form-factor failed" << std::endl; return false; } for (int i = 0; i < nqz_; i++) ff.push_back(p_ff[i]); std::cout << "** FF CPU compute time: " << compute_time << " ms." << std::endl; #endif delete [] qx; delete [] qy; delete [] qz; delete [] triangles; if (p_ff != NULL) delete [] p_ff; return true; }
bool NumericFormFactor::compute(const char * filename, complex_vec_t & ff, RotMatrix_t & rot #ifdef USE_MPI , woo::MultiNode &world_comm, std::string comm_key #endif ){ real_t comp_time = 0.0; // initialize init (rot, ff); unsigned int nqy = QGrid::instance().nqy(); unsigned int nqz = QGrid::instance().nqz_extended(); // warning: all procs read the shape file!!!! // TODO: improve to parallel IO, or one proc reading and sending to all ... // #ifndef __SSE3__ real_vec_t shape_def; // #else // #ifdef USE_GPU // real_vec_t shape_def; // #else // real_t* shape_def = NULL; // #endif // #endif // use the new file reader instead ... unsigned int num_triangles = read_shapes_file(filename, shape_def); // TODO ... <--- sadly all procs read this! IMPROVE!!! #ifdef USE_MPI int num_procs = world_comm.size(comm_key); int rank = world_comm.rank(comm_key); bool master = world_comm.is_master(comm_key); #else bool master = true; #endif if(master) { std::cout << "-- Numerical form factor computation ..." << std::endl << "** Using input shape file: " << filename << std::endl << "** Number of input triangles: " << num_triangles << std::endl << "** Q-grid resolution (q-points): " << nqz << std::endl #ifdef USE_MPI << "** Number of processes requested: " << num_procs << std::endl #endif << std::flush; } // if if(num_triangles < 1) { std::cerr << "error: no triangles found in specified definition file" << std::endl; return false; } // if // FIXME: this is a yucky temporary fix ... fix properly ... real_t* qx = new (std::nothrow) real_t[nqy](); real_t* qy = new (std::nothrow) real_t[nqy](); #ifdef FF_NUM_GPU cucomplex_t* qz = new (std::nothrow) cucomplex_t[nqz](); #else complex_t* qz = new (std::nothrow) complex_t[nqz](); #endif // create qy_and qz using qgrid instance for(unsigned int i = 0; i < nqy; ++ i) qx[i] = QGrid::instance().qx(i); for(unsigned int i = 0; i < nqy; ++ i) qy[i] = QGrid::instance().qy(i); for(unsigned int i = 0; i < nqz; ++ i) { #ifdef FF_NUM_GPU qz[i].x = QGrid::instance().qz_extended(i).real(); qz[i].y = QGrid::instance().qz_extended(i).imag(); #else qz[i] = QGrid::instance().qz_extended(i); #endif } // for #ifdef FF_NUM_GPU cucomplex_t *p_ff = NULL; #else complex_t *p_ff = NULL; #endif real_t kernel_time = 0.; unsigned int ret_numtriangles = 0; #ifdef FF_NUM_GPU // use GPU ret_numtriangles = gff_.compute_approx_triangle(shape_def, p_ff, nqy, qx, qy, nqz, qz, rot_, kernel_time); for (int i = 0; i < nqz; i++) ff.push_back(complex_t(p_ff[i].x, p_ff[i].y)); std::cout << "** FF GPU compute time: " << kernel_time << " ms." << std::endl; #else // use only CPU ret_numtriangles = cff_.compute_approx_triangle(shape_def, p_ff, nqy, qx, qy, nqz, qz, rot_, kernel_time); for (int i = 0; i < nqz; i++) ff.push_back(p_ff[i]); std::cout << "** FF CPU compute time: " << kernel_time << " ms." << std::endl; #endif if(p_ff != NULL) delete[] p_ff; delete[] qz; delete[] qy; delete[] qx; }
complex_t operator*(real_t s, complex_t c) { return complex_t(c.real() * s, c.imag() * s); } // operator*()
complex_t operator*(complex_t c, complex_t s) { return complex_t(c.real() * s.real() - c.imag() * s.imag(), c.real() * s.imag() + c.imag() * s.real()); } // operator*()
int main() { complex_t a, b, res; int op; void *lib; DIR *dir; struct dirent *entry; int n_dir; dir = opendir("./lib"); if (!dir) { perror("diropen"); exit(1); } for (n_dir = 0; (entry = readdir(dir)) != NULL; n_dir++) ; closedir(dir); char **arr_dir = (char **) calloc(n_dir, sizeof(char**)); if (!arr_dir) { printf("Ошибка при распределении памяти\n"); exit(1); } printf("\n"); while(1) { printf("Введите два числа:\n"); printf("a.re: "); scanf("%f", &a.r); printf("a.im: "); scanf("%f", &a.i); printf("b.re: "); scanf("%f", &b.r); printf("b.im: "); scanf("%f", &b.i); dir = opendir("./lib"); int c = 0; printf("\nВыберите библиотеку:\n"); while ((entry = readdir(dir)) != NULL) { if (strcmp(".", entry->d_name) && strcmp("..", entry->d_name)) { printf("%d) %s\n", c+1, entry->d_name); arr_dir[c] = (char *) calloc(200, sizeof(char)); strcpy(arr_dir[c], entry->d_name); c++; } } printf("> "); scanf("%d", &op); char tmp_path[strlen(arr_dir[op-1]) + 6]; bzero(tmp_path, sizeof(tmp_path)); strcat(tmp_path, "./lib/"); strcat(tmp_path, arr_dir[op-1]); printf("%s\n", arr_dir[op-1]); lib = load_lib(tmp_path); complex_t (*cplx_op_ptr) (complex_t a, complex_t b); /* Вырезаем lib и .so (libcplx_add.so -> cplx_add)*/ for (c = 3; arr_dir[op-1][c] != '.'; c++) tmp_path[c-3] = arr_dir[op-1][c]; tmp_path[c-3] = '\0'; cplx_op_ptr = dlsym(lib, tmp_path); res = (*cplx_op_ptr)(a, b); cplx_out(res); dlclose(lib); } int i; for (i = 0; i < n_dir; i++) free(arr_dir[i]); free(arr_dir); return 0; }
complex_t AnalyticFormFactor::sinc(complex_t value) { complex_t temp; if(fabs(value.real()) <= 1e-14 && fabs(value.imag()) <= 1e-14) temp = complex_t(1.0, 0.0); else temp = sin(value) / value; return temp; } // AnalyticFormFactor::sinc()