0. Final projects and other miscellaneous notes. 1. Defining vectors and matrices within C. 2. C functions communicating. 3. Running C from terminal. 4. Reading in from a file. 0. Final projects and other misc notes. HW3 is due by email Thu Nov 14, 1030am. Group 10 moved to 6. Tue, Nov 26 [1] DAS GUPTA, APARUPA . MAO, JUNHUA . WANG, PENG . [2] CAI, YUAN . SINGH, VIKRAM VIR . WU, GUANI . [3] LIU, YUNLEI . KARWA, ROHAN SUNIL . KUHFELD, MEGAN REBECCA . [4] MURPHY, JOHN LEE . HONG, JI YEON . SHAH, VAIBHAV CHETAN . [5] FERNANDEZ, KEITH EDWARD . AHLUWALIA, ANSUYA . HAROUNIAN, BENJAMIN . [6] XIE, MEIHUI . WONG, ALEX KING LAP . XIE, DAN . Tue, Dec 3 [7] Csapo, Marika . LEWIS, BRONWYN ASHLEIGH . ZHANG, QIANG . [8] NAN, XIAOMENG . ARELLANO, RYAN CHRISTOPHER . SHU, LE . [9] WANG, XINYUE . CHEN, JIAMIN . HAN, TIAN . [10] THAKUR, MANOJ RAMESHCHANDRA . POWELL, CHRISTOPHER GRANT . [11] TAN, MENGXIN . ROBERTS, SHANE WILLIAM STROUTH . HUANG, PENG JUN . [12] YU, CHENGCHENG . WU, JOHN SHING . MOUSAVI, SEYED ALI . Thu, Dec 5 [13] GU, JIAYING . RAMIREZ, ARTURO . DEMIRDJIAN, LEVON . [14] HUYNH, HIEN TRINH . SHEN, LINLING . CHANDRASEKHARAN, MANJANA . [15] WISNER, TRISTAN GARDNER . MAGYAR, ZSUZSANNA BLANKA . HE, JIA . [16] KRUMHOLZ, SAMUEL DAVID . KATTE, SAMIR RAJENDRA . WAINFAN, KATHRYN TANYA . [17] WANG, TENG . SCHWEIG, JONATHAN DAVID . Gupta, Hitesh . Rgooglemaps package is nice for adding maps to plots, by the way. For compiling C in Windows, these links might be useful: http://mcglinn.web.unc.edu/blog/linking-c-with-r-in-windows . http://www.stat.columbia.edu/~gelman/stuff_for_blog/AlanRPackageTutorial.pdf . http://cran.r-project.org/bin/windows/base rw-FAQ.html#How-do-I-include-compiled-C-code_003f . 1. Vectors and matrices in C. You can just say double x[100] or double x[25][4], for example. In mypi2.c, /* Calculate the first 100 terms in the approximation of pi. */ #include #include void pi100 (double *y){ int i; double x[100]; x[0] = 1.0; y[0] = sqrt(6.0); for(i = 1; i < 100; i++) { x[i] = x[i-1] + pow(i+1.0,-2.0); y[i] = sqrt(6.0 * x[i]); } } In R, system("R CMD SHLIB mypi2.c") dyn.load("mypi2.so") a = .C("pi100",y=double(100)) plot(1:100,a$y,type="l",xlab="n",ylab="Approx. of pi") In mypi3.c, /* Calculate 1*2*3 + 4*5*6 + ... + 28*29*30. */ #include #include void weirdsum (double *y){ int i,j; double x[10][3]; *y = 0.0; for(i = 0; i < 10; i++) { for(j = 0; j < 3; j++){ x[i][j] = 3*i + j + 1.0; } *y += x[i][0] * x[i][1] * x[i][2]; } } In R, system("R CMD SHLIB mypi3.c") dyn.load("mypi3.so") y = 1.0 a = .C("weirdsum",as.double(y)) a If you want x to be an n by m matrix, where n and m are inputs, you can just do, for instance, in mypi4.c, /* Calculate 1*2*3*...*m + (m+1)(m+2)...(2m) + ... + [(n-1)m+1][(n-1)m+2]...(nm). */ #include #include void pi103 (double *y, int *n, int *m){ int i,j; double x[*n][*m]; double a; /* First define the matrix. */ for(i = 0; i < *n; i++) { for(j = 0; j < *m; j++){ x[i][j] = *m*i + j + 1.0; } } /* Now multiply each row and add the product to y. */ *y = 0.0; for(i = 0; i < *n; i++){ a = 1.0; for(j = 0; j < *m; j++){ a *= x[i][j]; } *y += a; } } In R, system("R CMD SHLIB mypi4.c") dyn.load("mypi4.so") y = 1.0 a = .C("pi103",as.double(y),as.integer(10),as.integer(3)) a[[1]] ## to check, prod(1:3)+prod(4:6)+prod(7:9)+prod(10:12)+ prod(13:15)+prod(16:18)+prod(19:21)+prod(22:24)+prod(25:27)+prod(28:30) a = .C("pi103",result75=as.double(y),as.integer(8),as.integer(4)) a$y prod(1:4)+prod(5:8)+prod(9:12)+prod(13:16)+ prod(17:20)+prod(21:24)+prod(25:28)+prod(29:32) Note that you have to say "y = as.double(y)" rather than just as.double(y) if you want to be able to call the result with a$y. To do this in R, you could do n = 8 m = 4 x = matrix(1:(n*m),byrow=T,ncol=m) y = apply(x,1,prod) sum(y) What if you want to define a vector of length n, or a matrix with a dimension n, and n is not an input or a known integer but instead something that must be calculated inside your function, or something that changes as you go through your function? Then you need to do dynamic memory allocation. We will hopefully get to this later. 2. Calling C functions from C. In mysd1.c, /* Create a 10 x 4 matrix of integers and compute the sample SD of each row. */ /* Row 1 will be (1, 4, 9, 16). Row 2 will be (25, 36, 49, 64), etc. */ #include #include double sd2(double *x, int n){ int i; double xbar, b; xbar = 0.0; for(i = 0; i < n; i++){ xbar += x[i]; } xbar = xbar/n; b = 0.0; // b will be the sum of squared deviations for(i = 0; i < n; i++){ b += pow(x[i] - xbar, 2); } return(pow(b/(n-1),0.5)); } void rowsd (double *y){ int i,j; double a; double x[10][4]; for(i = 0; i < 10; i++) { for(j = 0; j < 4; j++){ x[i][j] = pow(4*i + j + 1.0, 2); } y[i] = sd2(x[i], 4); } } In R, system("R CMD SHLIB mysd1.c") dyn.load("mysd1.so") a = .C("rowsd",y=double(10)) a$y ## to check it, sd(c(1,4,9,16)) sd(c(25,36,49,64)) 3. Running C from terminal. In mypi5.c, #include #include int main ( ){ int i; float x,y,h; printf("\n How many years old are you? "); scanf("%d", &i); printf("\n How long is the first side of your right triangle? "); scanf("%f", &x); printf("\n How long is the second side of your right triangle? "); scanf("%f", &y); h = sqrtf(x*x + y*y); printf("\n You are %d years old and the hypotenuse is %f . \n", i, h); return(i); } In terminal on mac (or powershell on PC), cd /Users/fredericschoenberg/Documents/2012/202aF12/CinR, gcc mypi5.c -o mypi5.out ./mypi5.out 4. Reading in from a file. You first need a file pointer FILE *fp; FILE is a structure that holds information about the file. Use FILE * to pass the information around by reference. fp = fopen(filename, mode); filename is a string that holds the name of the file on disk (including a path like /cs/course if necessary). mode is a string representing how you want to open the file. Most often you'll open a file for reading ("r") or writing ("w"). In data.txt, 1 14 5 37 7 2 1 100 In readin1.c, #include #include #include void readssq (int *n){ /* Read in the first n terms in "data.txt" and compute the sum of squares. Write the output to "output.txt" */ FILE *myfile1, *myfile2; int i; float a1, a2; a2 = 0.0; myfile1 = fopen("data.txt", "r"); myfile2 = fopen("output.txt", "w"); for(i = 0; i < *n; i++){ fscanf(myfile1, "%f", &a1); a2 += pow(a1, 2); } fclose(myfile1); Rprintf("The sum of squares is %f \n", a2); fprintf(myfile2, "%f \n", a2); fclose(myfile2); } In R, system("R CMD SHLIB readin1.c") dyn.load("readin1.so") a = .C("readssq",as.integer(5)) The input file that we are opening for reading ("r") must already exist, but the output file we are opening for writing ("w") does not have to exist. If it doesn't, it will be created. If this output file does already exist, its previous contents will be thrown away and lost. Use "a" for append to write something to the end of a file without losing its contents. In fprintf, Integer values use %d, Floating point values, i.e. decimals, use %f, %lf for double precision numbers, Single characters use %c, Character strings use %s. Coming up. ## inputting and outputting matrices. ## Generalized additive models. ## Making R packages. ## Calling R from C.