Skip to content

Code of sample() in C

8 messages · Berwin A Turlach, Ranjan Maitra, Paul Smith

#
Dear All,

I would like to use the function sample() in a program written in C.
Is there somewhere the code of sample() written in C?

Thanks in advance,

Paul
#
Hi Paul,

It is in the main/src/random.c file of the source code.

HTH!
Best wishes,
Ranjan
On Sun, 5 Apr 2009 15:35:25 +0100 Paul Smith <phhs80 at gmail.com> wrote:

            
#
Thanks, Ranjan. Got it!

I am now wondering whether there is some simpler way of implementing
the following in C:

sample(1:50,5)

Paul
On Sun, Apr 5, 2009 at 4:10 PM, Ranjan Maitra <maitra at iastate.edu> wrote:
#
I presume you mean sampling without replacement? The following
(adapted from the file you asked for) will do it, but you will need to
incorporate Rmath as standalone in order to get runif to work.

This function will give you k indices from n, sampled WOR. Thus, n = 50
for you and k = 5. You will get a vector y of length 5 (a pointer of int
actually) which will contain these indices.

Thus you will define a vector z (of length 50) which is 1:50, and then
using the function, your SRWOR sample will be z[y[i]] where i = 0,
1,...4.

I haven't tried this function out much myself, so YMMV.

HTH!

Best wishes,
Ranjan



#include <stdlib.h>
#ifndef USING_RLIB
#define MATHLIB_STANDALONE 1 /*It is essential to have this before the call 
                               to the Rmath's header file because this decides
                               the definitions to be set. */
#endif
#include <Rmath.h>

/* Note that use of this function involves a prior call to the Rmath library to
   get the seeds in place. It is assumed that this is done in the calling 
   function. */

/* Equal probability sampling; without-replacement case */
/* Adapted from the R function called SampleNoReplace */

/**
 * Stores k out of n indices sampled at random without replacement
 * in y.
 */
int srswor(int n, int k, int *y)
{ 
  if (k > n) {
    return 1;
  }
  else {
    const double len = (double) n;
    int i;
    int* x = malloc(n * sizeof(int));
    if (!x) {
      return 2;
    }
		
    for (i = 0; i < n; ++i)	x[i] = i;
    
    for (i = 0; i < k; ++i) {
      const int j = (int)(len * runif(0.0, 1.0));
      y[i] = x[j];
      x[j] = x[--n];
    }
    free(x);
  }
  return 0;
}
On Sun, 5 Apr 2009 20:11:04 +0100 Paul Smith <phhs80 at gmail.com> wrote:

            
#
G'day Ranjan,

On Sun, 5 Apr 2009 17:00:56 -0500
Ranjan Maitra <maitra at iastate.edu> wrote:

            
There is an obvious problem in this code since len is not decreased but
n is when an index is sampled.  The last line in the last for loop
should be
	x[j] = x[--len];
Otherwise this algorithm will produce samples in which an index can
be repeated.  And the probabilities with which an index is sampled would
be non-trivial to determine; they would definitely not be uniform.

HTH.

Cheers,

	Berwin
=========================== Full address =============================
Berwin A Turlach                            Tel.: +65 6516 4416 (secr)
Dept of Statistics and Applied Probability        +65 6516 6650 (self)
Faculty of Science                          FAX : +65 6872 3919       
National University of Singapore     
6 Science Drive 2, Blk S16, Level 7          e-mail: statba at nus.edu.sg
Singapore 117546                    http://www.stat.nus.edu.sg/~statba
#
Thanks, Ranjan! I have tried to use the function SampleNoReplace in
random.c, which seems to work, except that I get always the same
random numbers (with your code the same happens). (My code is below.).

I have read the documentation ("Writing R extensions"), where it is advised:

?The interface to R?s internal random number generation routines is

double unif_rand();
double norm_rand();
double exp_rand();

giving one uniform, normal or exponential pseudo-random variate.
However, before these are used, the user must call

GetRNGstate();

and after all the required variates have been generated, call

PutRNGstate();?

However, when I use GetRNGstate() and PutRNGstate(), I get the following errors:

$ gcc -I/usr/include/R -o myprog myprog.c -lRmath -lm
/tmp/cc6CMnlh.o: In function `main':
myprog.c:(.text+0x30): undefined reference to `GetRNGstate'
myprog.c:(.text+0x57): undefined reference to `PutRNGstate'
collect2: ld returned 1 exit status
$

Any ideas?

Paul

--------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <R.h>
#include <Rmath.h>
#define MATHLIB STANDALONE
#include <math.h>

void snr(int k, int n, int *y, int *x);

int main()
{

  int *x = malloc(50*sizeof(int));
  int *y = malloc(5*sizeof(int));
  int i;

  GetRNGstate();
  snr(5,50,y,x);
  PutRNGstate();

  for(i=0;i<5;++i)
    printf("%d ",y[i]);

  free(x);
  free(y);

  return 0;

}


void snr(int k, int n, int *y, int *x)
{
    int i, j;
    for (i = 0; i < n; i++)
        x[i] = i;
    for (i = 0; i < k; i++) {
        j = n * unif_rand();
        y[i] = x[j] + 1;
        x[j] = x[--n];
    }
}

--------------------------------------
On Sun, Apr 5, 2009 at 11:00 PM, Ranjan Maitra <maitra at iastate.edu> wrote:
#
Hi Paul,

I believe that you may need to set seed differently when you call the R
math library as standalone. Specifically, you need to do the following
(or rather, the following works):

        unsigned int seed1, seed2;
	FILE *fran;
	
	fran = fopen("random.seed","r");
        fscanf(fran, "%u %u", &seed1, &seed2);
        fclose(fran); 

	set_seed(seed1, seed2);

where random.seed is the file containing two large integers. 

and after I am done, I usually add the following towards the end of the
main program....

        get_seed(&seed1, &seed2);
	
        fran=fopen("random.seed", "w");
        fprintf(fran, "%d %d\n", seed1, seed2);
        fclose(fran);

You will again need to include Rmath.h and declare the standalone parameter in the calling program also.


HTH!

Best wishes,
Ranjan
On Mon, 6 Apr 2009 10:41:19 +0100 Paul Smith <phhs80 at gmail.com> wrote:

            
#
Thanks again, Ranjan. I am wondering whether the seed can be set
(renewed) with GetRNGstate(). Furthermore, I would like to understand
why I am getting the reported compilation errors when I insert
GetRNGstate() in my code.

Paul
On Mon, Apr 6, 2009 at 12:17 PM, Ranjan Maitra <maitra at iastate.edu> wrote: