Thanks to visit codestin.com
Credit goes to code.bioconductor.org

#include <cmath>

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

#include <roptim.h>
// [[Rcpp::depends(roptim)]]
using namespace Rcpp;
using namespace roptim;

// You can include R code blocks in C++ files processed with sourceCpp
// (useful for testing and development). The R code will be automatically
// run after the compilation.
//

// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::vec NBthmDE_grad(arma::vec& y, arma::mat& X, arma::mat& Z, arma::vec& x, arma::vec& u, arma::vec& alpha0,
               arma::vec& alpha, arma::mat& preci1, double preci2, double threshold0){
  int n = X.n_cols;
  arma::vec gr = arma::zeros<arma::vec>(n+2);

  arma::vec beta = x(arma::span(0,n-1));
  double r = x(n);
  double threshold = x(n+1);

  arma::vec tmp0 = arma::exp2(X*beta+Z*u);
  arma::vec tmp1 = alpha0*threshold+alpha%tmp0;
  arma::vec tmp2 = (y/tmp1-1.0)/(1.0+tmp1/r);

  gr(arma::span(0,n-1)) = (-log(2.0)*(tmp2%alpha%tmp0).t()*X+beta.t()*preci1).t();

  arma::vec pLr = -arma::log(1.0+tmp1/r);
  for(int i = 0; i < y.n_elem; i++){
    for(int j = 0; j < y(i); j++){
      pLr(i) += 1.0/(j+r);
    }
  }
  pLr += -(y-tmp1)/(r+tmp1);
  gr(n) = -arma::sum(pLr);

  arma::mat tmp3 = tmp2.t()*alpha0;
  gr(n+1) = -tmp3(0,0)+(threshold-threshold0)*preci2;
  return gr;
}



// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::export]]
arma::mat NBthmDE_gradM(arma::vec& y, arma::mat& X, arma::mat& Z, arma::vec& x, arma::mat& u_mat, arma::vec& alpha0,
               arma::vec& alpha, arma::mat& preci1, double preci2, double threshold0){

    int n = X.n_cols;
    int nmh = u_mat.n_rows;
    int m = y.n_elem;



    arma::vec beta = x(arma::span(0,n-1));
    double r = x(n);
    double threshold = x(n+1);

    arma::mat tmp0 = Z*u_mat.t();

    arma::vec tmp00 = X*beta;

    tmp0.each_col() += tmp00;

    tmp0 = arma::exp2(tmp0);

    arma::mat tmp1=tmp0;

    tmp1.each_col() %= alpha;

    arma::vec tmp11 = alpha0*threshold;

    tmp1.each_col() += tmp11;

    arma::mat tmp2(m, nmh, arma::fill::zeros);

    arma::mat grm(n+2, nmh, arma::fill::zeros);

    arma::vec pLr(m);
    arma::mat tmp3(1,1);
    for(int i=0; i < nmh; i++){
      tmp2.col(i) = (y/tmp1.col(i)-1.0)/(1.0+tmp1.col(i)/r);
      grm(arma::span(0,n-1), i) = (-log(2.0)*(tmp2.col(i)%alpha%tmp0.col(i)).t()*X+beta.t()*preci1).t();
      pLr = -arma::log(1.0+tmp1.col(i)/r);
      for(int k = 0; k < y.n_elem; k++){
        for(int j = 0; j < y(k); j++){
          pLr(k) += 1.0/(j+r);
        }
      }
      pLr += -(y-tmp1.col(i))/(r+tmp1.col(i));
      grm(n, i) = -arma::sum(pLr);
      tmp3 = tmp2.col(i).t()*alpha0;
      grm(n+1, i) = -tmp3(0,0)+(threshold-threshold0)*preci2;
    }

    return grm;

}


/*** R

*/