date-performance 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. data/AUTHORS +1 -0
  2. data/BENCHMARKS +30 -0
  3. data/COPYING +22 -0
  4. data/README.txt +134 -0
  5. data/Rakefile +90 -0
  6. data/doc/asciidoc.conf +21 -0
  7. data/doc/changes.html +32 -0
  8. data/doc/changes.txt +7 -0
  9. data/doc/images/icons/callouts/1.png +0 -0
  10. data/doc/images/icons/callouts/10.png +0 -0
  11. data/doc/images/icons/callouts/11.png +0 -0
  12. data/doc/images/icons/callouts/12.png +0 -0
  13. data/doc/images/icons/callouts/13.png +0 -0
  14. data/doc/images/icons/callouts/14.png +0 -0
  15. data/doc/images/icons/callouts/15.png +0 -0
  16. data/doc/images/icons/callouts/2.png +0 -0
  17. data/doc/images/icons/callouts/3.png +0 -0
  18. data/doc/images/icons/callouts/4.png +0 -0
  19. data/doc/images/icons/callouts/5.png +0 -0
  20. data/doc/images/icons/callouts/6.png +0 -0
  21. data/doc/images/icons/callouts/7.png +0 -0
  22. data/doc/images/icons/callouts/8.png +0 -0
  23. data/doc/images/icons/callouts/9.png +0 -0
  24. data/doc/images/icons/caution.png +0 -0
  25. data/doc/images/icons/example.png +0 -0
  26. data/doc/images/icons/home.png +0 -0
  27. data/doc/images/icons/important.png +0 -0
  28. data/doc/images/icons/next.png +0 -0
  29. data/doc/images/icons/note.png +0 -0
  30. data/doc/images/icons/prev.png +0 -0
  31. data/doc/images/icons/tip.png +0 -0
  32. data/doc/images/icons/up.png +0 -0
  33. data/doc/images/icons/warning.png +0 -0
  34. data/doc/license.html +42 -0
  35. data/doc/license.txt +1 -0
  36. data/doc/stylesheets/handbookish-manpage.css +36 -0
  37. data/doc/stylesheets/handbookish-quirks.css +2 -0
  38. data/doc/stylesheets/handbookish.css +119 -0
  39. data/ext/date_performance.c +401 -0
  40. data/ext/extconf.rb +9 -0
  41. data/lib/date/memoize.rb +86 -0
  42. data/lib/date/performance.rb +44 -0
  43. data/misc/asciidoc.rake +121 -0
  44. data/misc/project.rake +922 -0
  45. data/test/date_memoize_test.rb +70 -0
  46. data/test/extension_test.rb +120 -0
  47. metadata +110 -0
@@ -0,0 +1,2 @@
1
+ /* Workarounds for IE6's broken and incomplete CSS2. */
2
+
@@ -0,0 +1,119 @@
1
+ body {
2
+ font-size:87.5%; /* 1em = 14px */
3
+ line-height:1.4285; /* 20px baseline */
4
+ margin:2.85em; /* 40px margins */
5
+ max-width:51.42857em; /* 720px max width */
6
+ font-family: 'Lucida Grande', 'Verdana', 'Helvetica', sans-serif;
7
+ color:#222;
8
+ }
9
+
10
+ em { font-style: italic }
11
+ strong { font-weight: bold }
12
+ tt { color:#007A00 }
13
+ dt { font-weight:bold }
14
+
15
+ h1, h2, h3, h4, h5 {
16
+ font-family: Verdana, Helvetica, sans-serif ;
17
+ color:#900 ;
18
+ }
19
+
20
+ h1 {
21
+ font-size:2.857em; /* 40px */
22
+ line-height:1.5; /* 60px */
23
+ border-bottom:0.05em; /* 2px; */
24
+ margin:0.5em 0; /* 20px */
25
+ }
26
+
27
+ h2 {
28
+ font-size:2.285em; /* 32px */
29
+ line-height:1.25; /* 40px */
30
+ border-bottom:0.0625em solid #fff; /* 2px border */
31
+ margin:0.906em 0; /* 29px margin */
32
+ }
33
+
34
+ h3 {
35
+ font-size:1.714em; /* 24px */
36
+ line-height:1.666; /* 40px */
37
+ border-bottom:0.0833em solid #fff; /* 2px border */
38
+ margin:0.75em 0; /* 18px */
39
+ }
40
+
41
+ h4 {
42
+ font-size:1.142em; /* 16px */
43
+ line-height:1.25; /* 20px */
44
+ border-bottom:0;
45
+ margin:1.25em 0; /* 20px */
46
+ }
47
+
48
+ pre {
49
+ font-size:1.1666em;
50
+ line-height:1.333;
51
+ }
52
+
53
+ pre tt { color:#000 }
54
+
55
+ p, ul, ol, dl {
56
+ margin:1.4285em 0; /* 20px */
57
+ }
58
+
59
+ dl {
60
+ margin-left:2.857em;
61
+ }
62
+
63
+ .title, .sidebar-title {
64
+ font-weight: bold;
65
+ margin-bottom:0;
66
+ }
67
+
68
+ .admonitionblock { margin:1.4285em; }
69
+
70
+ .admonitionblock td.icon {
71
+ width:2.857em; /* 40px */
72
+ padding-right:1.4285em;
73
+ }
74
+
75
+ .listingblock .content {
76
+ border: 1px solid silver;
77
+ background: #f4f4f4;
78
+ padding: 0.7142em; /* 10px */
79
+ }
80
+
81
+ .listingblock .content pre { margin:0 }
82
+ .literalblock .content { margin-left:2.8568em; }
83
+
84
+ .verseblock .content { white-space: pre }
85
+
86
+ .sidebarblock .sidebar-content {
87
+ border: 1px solid silver;
88
+ background: #FFFFEE;
89
+ padding: 0 1.428em; /* 20px */
90
+ color:#222;
91
+ }
92
+ .sidebar-title {
93
+ margin: 1.125em 0;
94
+ }
95
+
96
+ .quoteblock-content {
97
+ font-style:normal;
98
+ color:#555;
99
+ margin-left:2.857em;
100
+ }
101
+ .quoteblock-content .attribution {
102
+ font-style: normal;
103
+ text-align:right;
104
+ color:#000;
105
+ }
106
+
107
+ .exampleblock-content *:first-child { margin-top:0 }
108
+ .exampleblock-content {
109
+ border-left:2px solid silver;
110
+ padding-left:0.712em;
111
+ }
112
+
113
+ #footer {
114
+ font-size:0.857em; /* 12px */
115
+ line-height:1.666; /* 20px */
116
+ margin-top:3.333em; /* 40px */
117
+ border-top:1px solid silver;
118
+ color:#555;
119
+ }
@@ -0,0 +1,401 @@
1
+
2
+ /*
3
+ * Enable C99 extensions to enable fast float rounding stuff in math.h.
4
+ */
5
+ #define _ISOC9X_SOURCE 1
6
+ #define _ISOC99_SOURCE 1
7
+
8
+ #include <math.h>
9
+ #include <ruby.h>
10
+ #include <time.h>
11
+
12
+ #define FLOOR(a) lrintf(floorf(a))
13
+ #define FLOAT(a) (float)a
14
+
15
+ static VALUE rb_cDate; /* class Date */
16
+ static VALUE rb_cRational; /* class Rational */
17
+
18
+ static ID id_subtract; /* :- */
19
+ static ID id_add; /* :+ */
20
+ static ID id_divmod; /* :divmod */
21
+ static ID id_new; /* :new */
22
+ static ID id_new_bang; /* :new! */
23
+ static ID id_ivar_civil; /* :@__civil__ */
24
+ static ID id_jd; /* :jd */
25
+ static ID id_jd_to_civil; /* :jd_to_civil */
26
+ static ID id_ivar_sg; /* :@sg */
27
+ static ID id_numerator; /* :numerator */
28
+ static ID id_denominator; /* :denominator */
29
+
30
+ static ID id_strptime_without_performance;
31
+ static ID id_strftime_without_performance;
32
+
33
+ static VALUE JULIAN; /* Date::JULIAN */
34
+ static VALUE GREGORIAN; /* Date::GREGORIAN */
35
+ static VALUE ITALY; /* Date::ITALY */
36
+
37
+ static VALUE ra_one_half; /* Rational(1, 2) */
38
+ static VALUE DEFAULT_FORMAT; /* "%F" */
39
+
40
+ static int initialized = 0;
41
+
42
+ static inline int
43
+ civil_to_jd(int y, int m, int d, VALUE sg)
44
+ {
45
+ int a, b, jd;
46
+ if ( m <= 2 ) {
47
+ y-= 1;
48
+ m+= 12;
49
+ }
50
+ a = y / 100;
51
+ b = 2 - a + (a / 4);
52
+ jd = FLOOR(365.25 * (y + 4716)) +
53
+ FLOOR(30.6001 * (m + 1)) +
54
+ d + b - 1524;
55
+ if ( sg == JULIAN || (sg != GREGORIAN && jd < FIX2INT(sg)) )
56
+ jd -= b;
57
+ return jd;
58
+ }
59
+
60
+
61
+ /*
62
+ * Date::civil_to_jd(year, month, day, sg=Date::GREGORIAN)
63
+ */
64
+ static VALUE
65
+ rb_date_civil_to_jd(int argc, VALUE* argv, VALUE self)
66
+ {
67
+ int y = FIX2INT(argv[0]),
68
+ m = FIX2INT(argv[1]),
69
+ d = FIX2INT(argv[2]);
70
+ VALUE sg = (argc == 4 ? argv[3] : GREGORIAN);
71
+ return INT2FIX(civil_to_jd(y, m, d, sg));
72
+ }
73
+
74
+
75
+ struct mini_tm {
76
+ int y;
77
+ int m;
78
+ int d;
79
+ };
80
+
81
+
82
+ static inline void
83
+ jd_to_civil(int jd, VALUE sg, struct mini_tm * t)
84
+ {
85
+ int a, b, c, d, e;
86
+ if ( sg == JULIAN || (sg != GREGORIAN && jd < FIX2INT(sg)) ) { /* julian? */
87
+ a = jd;
88
+ }else{
89
+ int x = FLOOR((jd - 1867216.25) / 36524.25);
90
+ a = jd + 1 + x - FLOOR(x / 4.0);
91
+ }
92
+ b = a + 1524;
93
+ c = FLOOR((b - 122.1) / 365.25);
94
+ d = FLOOR(365.25 * c);
95
+ e = FLOOR((b - d) / 30.6001);
96
+ t->d = b - d - FLOOR(30.6001 * e);
97
+ if ( e <= 13 ) {
98
+ t->m = e - 1;
99
+ t->y = c - 4716;
100
+ }else{
101
+ t->m = e - 13;
102
+ t->y = c - 4715;
103
+ }
104
+ }
105
+
106
+
107
+ /*
108
+ * Date::jd_to_civil(jd, sg=GREGORIAN)
109
+ */
110
+ static VALUE
111
+ rb_date_jd_to_civil(int argc, VALUE * argv, VALUE self)
112
+ {
113
+ int jd = FIX2INT(argv[0]);
114
+ VALUE sg = (argc == 2 ? argv[1] : GREGORIAN);
115
+ struct mini_tm t;
116
+ jd_to_civil(jd, sg, &t);
117
+ return rb_ary_new3(3, INT2FIX(t.y), INT2FIX(t.m), INT2FIX(t.d));
118
+ }
119
+
120
+
121
+ /*
122
+ * Calculate the AJD from a julian date, fractional day, and offset.
123
+ */
124
+ static inline VALUE
125
+ jd_to_ajd(long jd, VALUE fr, VALUE of)
126
+ {
127
+ /* Ruby Implementation: jd + fr - of - 1.to_r/2 */
128
+ if ( TYPE(fr) == T_FIXNUM && TYPE(of) == T_FIXNUM ) {
129
+ /* fast path the common case of no fraction and no offset */
130
+ long numerator = (((jd + FIX2LONG(fr) - FIX2LONG(of)) - 1) * 2) + 1;
131
+ return rb_funcall(rb_cRational, id_new, 2, LONG2FIX(numerator), LONG2FIX(2));
132
+ }else{
133
+ /* use slower rational math */
134
+ VALUE result = rb_funcall(rb_cRational, id_new, 2, LONG2FIX(jd), LONG2FIX(1));
135
+ result = rb_funcall(result, id_add, 1, fr);
136
+ if ( of != LONG2FIX(0) )
137
+ result = rb_funcall(result, id_subtract, 1, of);
138
+ result = rb_funcall(result, id_subtract, 1, ra_one_half);
139
+ return result;
140
+ }
141
+ }
142
+
143
+
144
+ /*
145
+ * Date::jd_to_ajd(jd, fr, of=0)
146
+ */
147
+ static VALUE
148
+ rb_date_jd_to_ajd(int argc, VALUE * argv, VALUE self)
149
+ {
150
+ long jd = FIX2LONG(argv[0]);
151
+ VALUE fr = (argc > 1 ? argv[1] : LONG2FIX(0));
152
+ VALUE of = (argc > 2 ? argv[2] : LONG2FIX(0));
153
+ return jd_to_ajd(jd, fr, of);
154
+ }
155
+
156
+
157
+ /*
158
+ * Date::ajd_to_jd(ajd, of=0)
159
+ *
160
+ * TODO: handle offsets properly.
161
+ *
162
+ * Ruby Implementation: (ajd + of + 1.to_r/2).divmod(1)
163
+ */
164
+ static VALUE
165
+ rb_date_ajd_to_jd(int argc, VALUE * argv, VALUE self)
166
+ {
167
+ VALUE ajd = argv[0];
168
+ VALUE of = (argc == 2 ? argv[1] : INT2FIX(0));
169
+ long den = FIX2LONG(rb_funcall(ajd, id_denominator, 0));
170
+ long num = FIX2LONG(rb_funcall(ajd, id_numerator, 0));
171
+ if ( den == 2 && of == INT2FIX(0) ) {
172
+ /* fast path */
173
+ return rb_ary_new3(2, LONG2FIX((num + 1) / 2), ra_one_half);
174
+ }else{
175
+ VALUE result = rb_funcall(ajd, id_add, 1, of);
176
+ result = rb_funcall(result, id_add, 1, ra_one_half);
177
+ return rb_funcall(result, id_divmod, 1, LONG2FIX(1));
178
+ }
179
+ }
180
+
181
+
182
+ /*
183
+ * Date::new(y=-4712, m=1, d=1, sg=ITALY)
184
+ */
185
+ static VALUE
186
+ rb_date_new(int argc, VALUE * argv, VALUE self) {
187
+ int y = (argc > 0 ? NUM2INT(argv[0]) : -4712),
188
+ m = (argc > 1 ? NUM2INT(argv[1]) : 1),
189
+ d = (argc > 2 ? NUM2INT(argv[2]) : 1);
190
+ VALUE sg = (argc > 3 ? argv[3] : ITALY);
191
+ int jd = -1;
192
+ struct mini_tm t;
193
+ if (d < 0) {
194
+ int ny = (y * 12 + m) / 12;
195
+ int nm = (y * 12 + m) % 12;
196
+ nm = (nm + 1) / 1;
197
+ jd = civil_to_jd(ny, nm, d+1, sg);
198
+
199
+ VALUE ns = jd < 2299161 ? JULIAN : GREGORIAN;
200
+ jd_to_civil(jd-d, ns, &t);
201
+ if ( t.y != ny || t.m != nm || t.d != 1 ) {
202
+ rb_raise(rb_eArgError, "Invalid date: (%d, %d, %d)", y, m, d);
203
+ return Qnil;
204
+ }
205
+ jd_to_civil(jd, sg, &t);
206
+ if ( t.y != y || t.m != m ) {
207
+ rb_raise(rb_eArgError, "Invalid date: (%d, %d, %d)", y, m, d);
208
+ return Qnil;
209
+ }
210
+ } else {
211
+ jd = civil_to_jd(y, m, d, sg);
212
+ jd_to_civil(jd, sg, &t);
213
+ if ( t.y != y || t.m != m || t.d != d ) {
214
+ rb_raise(rb_eArgError, "Invalid date: (%d, %d, %d)", y, m, d);
215
+ return Qnil;
216
+ }
217
+ }
218
+ VALUE ajd = jd_to_ajd(jd, INT2FIX(0), INT2FIX(0));
219
+ VALUE date = rb_funcall(self, id_new_bang, 3, ajd, INT2FIX(0), sg);
220
+ rb_ivar_set(date, id_ivar_civil, rb_ary_new3(3, INT2FIX(t.y), INT2FIX(t.m), INT2FIX(t.d)));
221
+ return date;
222
+ }
223
+
224
+
225
+ /*
226
+ * Date#civil
227
+ *
228
+ * Fast path the case where the date is created with civil parameters.
229
+ */
230
+ static VALUE
231
+ rb_date_civil(VALUE self) {
232
+ if ( rb_ivar_defined(self, id_ivar_civil) == Qfalse ) {
233
+ VALUE jd = rb_funcall(self, id_jd, 0);
234
+ VALUE sg = rb_ivar_get(self, id_ivar_sg);
235
+ VALUE result = rb_funcall(rb_cDate, id_jd_to_civil, 2, jd, sg);
236
+ return rb_ivar_set(self, id_ivar_civil, result);
237
+ }else{
238
+ return rb_ivar_get(self, id_ivar_civil);
239
+ }
240
+ }
241
+
242
+
243
+ /*
244
+ * Date#sys_strftime(fmt="%F")
245
+ */
246
+ static VALUE
247
+ rb_date_strftime(int argc, VALUE * argv, VALUE self)
248
+ {
249
+ VALUE format = (argc > 0 ? *argv : DEFAULT_FORMAT);
250
+ VALUE civil = rb_date_civil(self);
251
+
252
+ char * pf = RSTRING(format)->ptr;
253
+ VALUE * pc = RARRAY(civil)->ptr;
254
+ int ic[3];
255
+
256
+ ic[0] = FIX2INT(pc[0]);
257
+ ic[1] = FIX2INT(pc[1]);
258
+ ic[2] = FIX2INT(pc[2]);
259
+
260
+ /* fast path default format: %F or %Y-%m-%d */
261
+ if ( (pf[0] == '%' && pf[1] == 'F' && pf[2] == 0) ||
262
+ (pf[0] == '%' && pf[1] == 'Y' && pf[2] == '-'
263
+ && pf[3] == '%' && pf[4] == 'm' && pf[5] == '-'
264
+ && pf[6] == '%' && pf[7] == 'd' && pf[8] == 0) )
265
+ {
266
+ VALUE buf = rb_str_buf_new(11);
267
+ char * pb = RSTRING(buf)->ptr;
268
+ RSTRING(buf)->len =
269
+ sprintf(pb, "%04d-%02d-%02d", ic[0], ic[1], ic[2]);
270
+ return buf;
271
+ }
272
+
273
+ /* Use libc's strftime but only for Date class */
274
+ if ( RBASIC(self)->klass == rb_cDate ){
275
+ VALUE buf = rb_str_buf_new(128);
276
+ char * pb = RSTRING(buf)->ptr;
277
+ struct tm t;
278
+ bzero(&t, sizeof(struct tm));
279
+ t.tm_year = ic[0] - 1900;
280
+ t.tm_mon = ic[1] - 1;
281
+ t.tm_mday = ic[2];
282
+ mktime(&t); /* fill in missing items (tm_wday, tm_yday) */
283
+ if ( (RSTRING(buf)->len = strftime(pb, 128, pf, &t)) > 0 )
284
+ return buf;
285
+ }
286
+
287
+ /* fall back on Ruby implementation if libc's strftime fails */
288
+ return rb_funcall2(self, id_strftime_without_performance, argc, argv);
289
+ }
290
+
291
+
292
+ /*
293
+ * Date::strptime(str="-4712-01-01", fmt='%F')
294
+ */
295
+ static VALUE
296
+ rb_date_strptime(int argc, VALUE * argv, VALUE self)
297
+ {
298
+ char *pe;
299
+ struct tm buf;
300
+ VALUE str = (argc > 0 ? argv[0] : rb_str_new2("-4712-01-01")),
301
+ fmt = (argc > 1 ? argv[1] : DEFAULT_FORMAT),
302
+ sg = (argc > 2 ? argv[2] : ITALY);
303
+ char * ps = RSTRING(str)->ptr;
304
+ char * pf = RSTRING(fmt)->ptr;
305
+ VALUE parts[4];
306
+
307
+ /* fast path default format */
308
+ if ( (pf[0] == '%' && pf[1] == 'F' && pf[0])
309
+ || (pf[0] == '%' && pf[1] == 'Y' && pf[2] == '-'
310
+ && pf[3] == '%' && pf[4] == 'm' && pf[5] == '-'
311
+ && pf[6] == '%' && pf[7] == 'd' && pf[8] == 0) )
312
+ {
313
+ parts[0] = INT2FIX(strtol(ps, &pe, 10));
314
+ parts[1] = Qnil;
315
+ parts[2] = Qnil;
316
+ parts[3] = sg;
317
+ if( pe == ps + 4 ) {
318
+ parts[1] = INT2FIX(strtol(ps + 5, &pe, 10));
319
+ if ( pe == ps + 7 ) {
320
+ parts[2] = INT2FIX(strtol(ps + 8, &pe, 10));
321
+ if ( pe == ps + 10 )
322
+ return rb_date_new(4, (VALUE*)&parts, self);
323
+ }
324
+ }
325
+ }
326
+
327
+ /* fall back on strptime(3) */
328
+ if ( strptime(ps, pf, &buf) )
329
+ {
330
+ parts[0] = INT2FIX(buf.tm_year + 1900);
331
+ parts[1] = INT2FIX(buf.tm_mon + 1);
332
+ parts[2] = INT2FIX(buf.tm_mday);
333
+ parts[3] = sg;
334
+ return rb_date_new(4, (VALUE*)&parts, self);
335
+ }
336
+
337
+ /* if that doesn't work, fall back on Ruby implementation */
338
+ return rb_funcall2(self, id_strptime_without_performance, argc, argv);
339
+ }
340
+
341
+
342
+ VALUE
343
+ Init_date_performance() {
344
+ /* initialization is not idemponent - make sure it only happens once. */
345
+ if ( initialized )
346
+ rb_raise(rb_eStandardError, "date_performance extension already initialized.");
347
+ initialized = 1;
348
+
349
+ /* Grab Date class */
350
+ rb_require("date");
351
+ rb_cDate = rb_define_class("Date", rb_cObject);
352
+
353
+ if( ! rb_const_defined_from(rb_cDate, rb_intern("Performance")) )
354
+ rb_raise(rb_eStandardError,
355
+ "Date::Performance not defined. The date_performance extension can not be required directly.");
356
+
357
+ /* Date Instance Methods */
358
+ rb_define_method(rb_cDate, "civil", rb_date_civil, 0);
359
+ rb_define_method(rb_cDate, "sys_strftime", rb_date_strftime, -1);
360
+ rb_define_method(rb_cDate, "strftime", rb_date_strftime, -1);
361
+
362
+ /* Date Singleton Methods */
363
+ rb_define_singleton_method(rb_cDate, "civil_to_jd", rb_date_civil_to_jd, -1);
364
+ rb_define_singleton_method(rb_cDate, "jd_to_civil", rb_date_jd_to_civil, -1);
365
+ rb_define_singleton_method(rb_cDate, "jd_to_ajd", rb_date_jd_to_ajd, -1);
366
+ rb_define_singleton_method(rb_cDate, "ajd_to_jd", rb_date_ajd_to_jd, -1);
367
+ rb_define_singleton_method(rb_cDate, "new", rb_date_new, -1);
368
+ rb_define_singleton_method(rb_cDate, "civil", rb_date_new, -1);
369
+ rb_define_singleton_method(rb_cDate, "sys_strptime", rb_date_strptime, -1);
370
+ rb_define_singleton_method(rb_cDate, "strptime", rb_date_strptime, -1);
371
+
372
+ /* Date Related Constants */
373
+ JULIAN = rb_eval_string("Date::JULIAN");
374
+ GREGORIAN = rb_eval_string("Date::GREGORIAN");
375
+ ITALY = INT2FIX(2299161);
376
+
377
+ DEFAULT_FORMAT = rb_str_new2("%F");
378
+ rb_gc_register_address(&DEFAULT_FORMAT);
379
+
380
+ /* Symbol Constants */
381
+ id_subtract = rb_intern("-");
382
+ id_add = rb_intern("+");
383
+ id_divmod = rb_intern("divmod");
384
+ id_new = rb_intern("new");
385
+ id_jd = rb_intern("jd");
386
+ id_jd_to_civil = rb_intern("jd_to_civil");
387
+ id_ivar_civil = rb_intern("@__civil__");
388
+ id_ivar_sg = rb_intern("@sg");
389
+ id_new_bang = rb_intern("new!");
390
+ id_numerator = rb_intern("numerator");
391
+ id_denominator = rb_intern("denominator");
392
+ id_strptime_without_performance = rb_intern("strptime_without_performance");
393
+ id_strftime_without_performance = rb_intern("strftime_without_performance");
394
+
395
+ /* Rational Stuff */
396
+ rb_require("rational");
397
+ rb_cRational = rb_define_class("Rational", rb_cNumeric);
398
+ ra_one_half = rb_funcall(rb_cRational, id_new, 2, INT2FIX(1), INT2FIX(2));
399
+ rb_gc_register_address(&ra_one_half);
400
+ return Qnil;
401
+ }