Использование функции Бесселка в C MexFunction - PullRequest
0 голосов
/ 25 июня 2018

Я хотел бы реализовать корреляционную функцию Matern в C mexFunction, которая требует вычисления для модифицированной функции Бесселька второго рода.

В MATLAB можно использовать функцию besselk.Тем не менее, нет такого эквивалента в любой библиотеке C (я прав?).Я знал, что библиотека boost (библиотека C ++) предоставляет доступ к модифицированной функции Besselk второго типа, см. https://en.cppreference.com/w/cpp/experimental/special_math,, но у меня возникают проблемы с ее работой в моей функции C mexFunction с MATLAB 2018a на моем Mac.как система Linux.Кстати, я не хочу вызывать функцию MATLAB besselk внутри кода C mex.

Любые предложения будут оценены.Ниже приведен минимальный пример построения материнской корреляционной функции с использованием C-мекс-кода.

#include "mex.h"
#include "matrix.h"
#include <math.h>
//#include <boost/math/special_functions.hpp>
double matern(double h, double nu)
{
    double tau = sqrt(2.0*nu) * h;
    double c = 0.0;
    if(h>0.0){
      c = (pow(tau, nu) * pow(2.0, 1.0-nu) / tgamma(nu)) * boost::math::cyl_bessel_k(nu, tau);
    }else{
      c = 1.0;
    }
    return c;
  }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    if(nrhs!=2){
        mexErrMsgTxt("Two Inputs are required.");
    }
    double h = mxGetScalar(prhs[0]);
    double nu = mxGetScalar(prhs[1]);
    double corr = matern(h, nu);
    mexPrint("matern(h=%g, nu=%g) = %g", h, nu, corr);
    plhs[0] = mxCreateDoubleMatrix(1, 1, mxREAL);
    mxSetPr(plhs[0], &corr);
         return;
}

Если я переведу приведенный выше код C mex в файл кода C ++, я смогу успешно получить код C ++, скомпилированный с помощью компилятора g ++, на моем Mac.

#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#include <boost/math/special_functions.hpp>

double matern(const double h, const double nu)
{

  double tau = sqrt(2.0*nu) * h;

  double c = 0.0;
  if(h>0.0){
    c = (pow(tau, nu) * pow(2.0, 1.0-nu) / tgamma(nu)) * boost::math::cyl_bessel_k(nu, tau);
  }else{
    c = 1.0;
  }


  return c;
}

int main(){
    double nu=0.5, h=1.0;
    double corr = matern(h, nu);
    printf("corr=%lf\n", corr);

    return 0;
}

Чтобы еще раз подчеркнуть мой вопрос, мне не нужен код C ++, вместо этого я хотел бы, чтобы мой код C mex успешно выполнялся.

1 Ответ

0 голосов
/ 26 июня 2018

Это не совсем для Mex.

Вы можете использовать специальные математические функции Boost из программы на Си; они предназначены для использования в C или C ++.

Для этого нужно добавить

#include <boost/math/tr1.hpp>

В C ++ объявления в этом файле вставляются в пространство имен booth::math, но очевидно, что вы не можете использовать пространства имен C ++ в C-коде. Сами функции скомпилированы с C-связью, поэтому они являются глобальными именами и могут быть просто использованы как есть.

Обратите внимание, что Boost предоставляет специальные математические функции как C99, так и TR1 (поэтому его можно использовать со стандартной библиотекой C, которая предшествует C99, если вы все еще живете в прошлом), но они находятся в разных библиотеках, как описано в документация Boost . Даже если у вас есть стандартная библиотека C99, после включения заголовка Boost вам потребуется использовать библиотеки Boost для функций C99. Таким образом, вам, вероятно, потребуется добавить две опции ссылки в вашу команду сборки:

-lboost_math_c99 -lboost_math_tr1

Если вам нужны версии float или long double, вам понадобятся другие библиотеки. Подробности смотрите в приведенной выше ссылке на документацию Boost.

...