Skip to content

complex values in C

3 messages · Terry Therneau, Iris Simmons, Rui Barradas

#
I've often used the following paradym in C code to define a list object returned to R

 ? ? static const char *outnames[]= {"dvec", "A", "Ainv",? "P", ""};
 ? ? SEXP rval, stemp;
 ? ? double *dvec, *A, *Ainv;
 ? ? int *P;


 ? ? PROTECT(rval = mkNamed(VECSXP, outnames));
 ? ? stemp=? SET_VECTOR_ELT(rval, 0, allocVector(REALSXP, nc));
 ? ? dvec= REAL(stemp);
 ? ? stemp = SET_VECTOR_ELT(rval, 1, allocMatrix(REALSXP, nc, nc));
 ? ? A = REAL(stemp);

Then the code puts values into dvec[i] and etc. and finally returns rval.

I'm missing how to do this when returning a complex value.? ?I've looked through the 
"Writing R extension" manual and have come up dry.? What am I missing?

Terry T.
#
I'm not sure if I know exactly what you're saying, so sorry if this
doesn't answer your question.

Everywhere you write double *, replace it with Rcomplex *
Replace REALSXP with CPLXSXP
Replace REAL() with COMPLEX()
When getting / / setting the real and imaginary parts, use x.r and x.i
and x.r = u and x.i = v

On Fri, Mar 13, 2026 at 10:25?PM Therneau, Terry M., Ph.D. via R-help
<r-help at r-project.org> wrote:
#
?s 02:25 de 14/03/2026, Therneau, Terry M., Ph.D. via R-help escreveu:
Hello,

Use CPLXSXP, COMPLEX and Rcomplex.
There are also Rf_asComplex, Rf_isComplex and Rf_ScalarComplex.
See section 5.2 [1] for a description of R type Rcomplex.

Maybe this example can help.



//---
// file: test_complex.c
#include <R.h>
#include <Rinternals.h>

SEXP complex1(const SEXP size) {
     SEXP cval;
     Rcomplex *cvec;
     const R_xlen_t n = Rf_asInteger(size);

     PROTECT(cval = allocVector(CPLXSXP, n));
     cvec = COMPLEX(cval);
     for(R_xlen_t i = 0; i < n; i++) {
         cvec[i].r = i + 1.0;
         cvec[i].i = 2.0 * (i + 1);
     }
     UNPROTECT(1);
     return cval;
}

SEXP complex2(void) {
     static const char *outnames[]= {"dvec", "complex", ""};
     SEXP rval, stemp;
     double *dvec;
     Rcomplex *cvec;

     const R_xlen_t nc = 2;

     PROTECT(rval = mkNamed(VECSXP, outnames));
     // reals
     stemp = SET_VECTOR_ELT(rval, 0, allocVector(REALSXP, nc));
     dvec= REAL(stemp);
     for(R_xlen_t i = 0; i < nc; i++)
         dvec[i] = 0.5 * (i + 1);
     // complex
     stemp = SET_VECTOR_ELT(rval, 1, allocVector(CPLXSXP, nc));
     cvec = COMPLEX(stemp);
     for(R_xlen_t i = 0; i < nc; i++) {
         cvec[i].r = i + 1.0;
         cvec[i].i = 2.0 * (i + 1);
     }
     // done
     UNPROTECT(1);
     return rval;
}

Now the R source to test the above

#---
# file: test_complex.R
dynLoad <- function(dynlib) {
   dynlib <- paste0(dynlib, .Platform$dynlib.ext)
   dyn.load(dynlib)
}
dynUnload <- function(dynlib) {
   dynlib <- paste0(dynlib, .Platform$dynlib.ext)
   dyn.unload(dynlib)
}

args <- c("CMD", "SHLIB", "test_complex.c")
system2("R", args = args)

dynLoad("test_complex")

complex1 <- function(size) .Call("complex1", as.integer(size))
complex2 <- function() .Call("complex2")

complex1(10L)
#>  [1]  1+ 2i  2+ 4i  3+ 6i  4+ 8i  5+10i  6+12i  7+14i  8+16i  9+18i 
10+20i
complex2()
#> $dvec
#> [1] 0.5 1.0
#>
#> $complex
#> [1] 1+2i 2+4i

dynUnload("test_complex")




[1] 
https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Interface-functions-_002eC-and-_002eFortran

Hope this helps,

Rui Barradas