[READ-ONLY] Mirror of https://github.com/shuuji3/python-extension-twister. Experimental Python C extension to generate random numbers by using Mersenne twister
3.3 kB
129 lines
1#include <Python.h>
2
3#include <stdio.h>
4#include <time.h>
5
6#include "SFMT-src-1.5.1/SFMT.h"
7
8// 乱数のデータが格納される構造体
9sfmt_t sfmt;
10
11/**
12 * 整数の乱数を num 個 print する関数
13 * @param num print する乱数の数を指定する
14 */
15void print_rand_int(int num) {
16 // Print header
17 printf("# print %d random int\n", num);
18 fflush(stdout);
19
20 // Print rand
21 for (int i = 0; i < num; i++) {
22 printf("%10llu ", sfmt_genrand_uint64(&sfmt));
23 if (i % 5 == 4) printf("\n");
24 }
25 printf("\n");
26 fflush(stdout);
27}
28
29/**
30 * [0, 1) の乱数を num 個 print する関数
31 * @param num print する乱数の数を指定する
32 */
33void print_rand(int num) {
34 // Print header
35 printf("# print %d random numbers\n", num);
36 fflush(stdout);
37
38 // Print rands
39 for (int i = 0; i < num; i++) {
40 printf("%10.8f ", sfmt_genrand_real2(&sfmt));
41 if (i % 5 == 4) printf("\n");
42 }
43 printf("\n");
44 fflush(stdout);
45}
46
47/**
48 * print_rand_int() を実行する Python メソッド
49 */
50static PyObject *
51twister_print_rand_int(PyObject *self, PyObject *args) {
52 int num = 10;
53 if (!PyArg_ParseTuple(args, "|l", &num)) {
54 return NULL;
55 }
56 print_rand_int(num);
57 Py_RETURN_NONE;
58}
59
60/**
61 * print_rand() を実行する Python メソッド
62 */
63static PyObject *
64twister_print_rand(PyObject *self, PyObject *args) {
65 int num = 10;
66 if (!PyArg_ParseTuple(args, "|l", &num)) {
67 return NULL;
68 }
69 print_rand(num);
70 Py_RETURN_NONE;
71}
72
73/**
74 * 乱数を1つ生成する Python メソッド
75 */
76static PyObject *
77twister_random(PyObject *self, PyObject *args) {
78 return PyFloat_FromDouble(sfmt_genrand_real2(&sfmt));
79}
80
81/**
82 * 乱数を1つ生成する Python メソッド
83 */
84static PyObject *
85twister_randint(PyObject *self, PyObject *args) {
86 // [start, end) のパラメータをパースする
87 long start, end;
88 if (!PyArg_ParseTuple(args, "ll", &start, &end)) {
89 return NULL;
90 }
91
92 // [0, 1) の乱数を、指定した範囲に正規化して、整数に変換する
93 double r = sfmt_genrand_real2(&sfmt);
94 return PyLong_FromLong((long)(r * (end - start) + start));
95}
96
97/**
98 * 拡張モジュールのメソッドの定義
99 */
100static PyMethodDef TwisterMethods[] = {
101 {"print_rand_int", twister_print_rand_int, METH_VARARGS, "Print random int num times."},
102 {"print_rand", twister_print_rand, METH_VARARGS, "Print random x in [0, 1) num times."},
103 {"random", twister_random, METH_VARARGS, "Generate a random number x in [0, 1)."},
104 {"randint", twister_randint, METH_VARARGS, "Generate a random int in the range [start, end)."},
105 {NULL, NULL},
106};
107
108/**
109 * 拡張モジュールの定義
110 */
111static struct PyModuleDef twistermodule = {
112 PyModuleDef_HEAD_INIT,
113 "twister",
114 "Generate random numbers by using Mersenne twister.",
115 -1,
116 TwisterMethods,
117};
118
119/**
120 * モジュール読み込み時に行われる初期化処理
121 * @return
122 */
123PyMODINIT_FUNC
124PyInit_twister(void) {
125 // 現在時刻をシードに与えて乱数を初期化する
126 sfmt_init_gen_rand(&sfmt, (uint32_t) time(NULL));
127
128 return PyModule_Create(&twistermodule);
129}