void mex(int nlhs, mxArray *plhs[], int nrhs, mxArray const *prhs[]) { if (nrhs != 4) mexErrMsgTxt("Needs 4 input arguments"); if (nlhs != 1) mexErrMsgTxt("Needs 1 output arguments"); mxArray *&aX = plhs[0]; // 1 x N output samples mxArray const *aQ = prhs[0], // 1 x K input alias probabilities *aJ = prhs[1], // 1 x K input alias table *aR = prhs[2], // 1 x N input uniform sample 1 *aV = prhs[3]; // 1 x N input uniform sample 2 int K = mxGetN(aQ), // number of outcomes N = mxGetN(aR); // number of samples if(mxGetM(aQ) != 1) mexErrMsgTxt("Dimensions of argument 1 invalid."); if(mxGetM(aJ) != 1 || mxGetN(aJ) != K) mexErrMsgTxt("Dimensions of arguments 1,2 inconsistent."); if(mxGetM(aR) != 1) mexErrMsgTxt("Dimensions of argument 3 invalid."); if(mxGetM(aV) != 1 || mxGetN(aV) != N) mexErrMsgTxt("Dimensions of arguments 3,4 inconsistent."); if(mxGetClassID(aQ) != float_type<F>()) mexErrMsgTxt("Argument 1 has incorrect floating point class."); if(mxGetClassID(aJ) != int_type<I>()) mexErrMsgTxt("Argument 2 has incorrect integer class."); if(mxGetClassID(aR) != float_type<F>()) mexErrMsgTxt("Argument 3 has incorrect floating point class."); if(mxGetClassID(aV) != float_type<F>()) mexErrMsgTxt("Argument 4 has incorrect floating point class."); aX = mxCreateNumericMatrix(1, N, int_type<I>(), mxREAL); I *X = (I*) mxGetPr(aX); // output samples F *Q = (F*) mxGetPr(aQ); // input alias probabilities I *J = (I*) mxGetPr(aJ); // input alias table F *R = (F*) mxGetPr(aR); // input uniform sample 1 F *V = (F*) mxGetPr(aV); // input uniform sample 2 alias_draw(K, N, X, Q, J, R, V); }
int main (int argc, char**argv) { FILE *file; FILE *tmp; uint64_t j, i = 0; uint32_t *res; uint32_t *map; uint32_t *cnt; uint32_t draw; double *table; double c = 0; /* getopt */ int opt; int option_index = 0; static const char *optstring = "1:2:c:N:a:f:m:i"; static const struct option long_options[] = { {"alpha", required_argument, 0, 'a'}, {"elements", required_argument, 0, 'N'}, {"universe", required_argument, 0, 'm'}, {"count", required_argument, 0, 'c'}, {"file", required_argument, 0, 'f'}, {"seed1", required_argument, 0, '1'}, {"seed2", required_argument, 0, '2'}, {"info", required_argument, 0, 'i'}, }; double alpha = 0.5; uint64_t count = (1 << 25); uint32_t N = (1 << 20); uint32_t m = UINT32_MAX; char *filename = NULL; while( (opt = getopt_long(argc, argv, optstring, long_options, &option_index)) != -1) { switch(opt) { case 'a': alpha = strtod(optarg, NULL); break; case 'N': N = strtol(optarg, NULL, 10); break; case 'm': m = strtol(optarg, NULL, 10); break; case 'c': count = strtoll(optarg, NULL, 10); break; case 'f': filename = strndup(optarg, 256); break; case '1': I1 = strtoll(optarg, NULL, 10); break; case '2': I2 = strtoll(optarg, NULL, 10); break; case 'i': default: printusage(argv); exit(EXIT_FAILURE); } if ( errno != 0 ) { if (filename != NULL) { free(filename); } xerror(strerror(errno), __LINE__, __FILE__); } } if (filename == NULL) { printusage(argv); exit(EXIT_FAILURE); } cnt = xmalloc( sizeof(uint32_t) * N ); map = xmalloc( sizeof(uint32_t) * N ); table = xmalloc( sizeof(double) * N ); res = xmalloc( sizeof(uint32_t) * BUFFER ); tmp = tmpfile(); file = fopen(filename, "wb"); if ( file == NULL ) { free(cnt); free(res); free(map); free(filename); free(table); xerror("Failed to open/create file.", __LINE__, __FILE__); } fprintf(file, "#N: %"PRIu32"\n", N); fprintf(file, "#Universe: %"PRIu32"\n", m); fprintf(file, "#Alpha: %lf\n", alpha); fprintf(file, "#Count: %"PRIu64"\n", count); fprintf(file, "#Filename: %s\n", filename); fprintf(file, "#Seed1: %"PRIu32"\n", I1); fprintf(file, "#Seed2: %"PRIu32"\n", I2); for (i = 1; i <= N; i++) { table[i-1] = pow( (double)i, alpha ); c = c + (1. / table[i-1]); } c = 1./c; for (i = 0; i < N; i++) { cnt[i] = 0; map[i] = i; table[i] = (c / table[i]); } shuffle(map, N); for (i = N; i < m; i++) { j = xuni_rand()*(i+1); if (j < N) { map[j] = i; } } alias_t *a = alias_preprocess(N, table); free(table); i = 0; while ( likely(i < count) ) { memset(res, '\0', sizeof(uint32_t)*BUFFER); for (j = 0; likely( (i < count && j < BUFFER) ); j++, i++) { draw = (uint32_t)alias_draw(a); cnt[draw] += 1; res[j] = map[draw]; } if ( unlikely(fwrite(res, sizeof(uint32_t), j, tmp) < j) ) { fclose(file); fclose(tmp); free(res); free(filename); free(map); xerror("Failed to write all data.", __LINE__, __FILE__); } } alias_free(a); quicksort_map(cnt, 0, N-1, map); // Print the weights of the top k probabilities into header of file fprintf(file, "#====== TOP %d ======\n", TOPK); for (i = 0; i < TOPK && i < N; i++) { fprintf(file, "#%"PRIu32": %.10lf\n", map[i], (double)cnt[i]/count); } fprintf(file, "\n"); rewind(tmp); memset(res, '\0', sizeof(uint32_t)*BUFFER); uint32_t err; while ( (err = fread(res, sizeof(uint32_t), BUFFER, tmp)) > 0 ) { if ( unlikely(fwrite(res, sizeof(uint32_t), err, file) < err) ) { fclose(file); fclose(tmp); free(res); free(filename); free(map); xerror("Failed to write all data.", __LINE__, __FILE__); } } fclose(file); fclose(tmp); free(res); free(filename); free(map); return EXIT_SUCCESS; }