tioga 1.6 → 1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/Tioga_README +35 -10
- data/split/Dvector/dvector.c +264 -22
- data/split/Dvector/lib/Dvector_extras.rb +30 -2
- data/split/Flate/extconf.rb +1 -1
- data/split/Function/function.c +112 -2
- data/split/Tioga/figures.c +76 -77
- data/split/Tioga/figures.h +375 -490
- data/split/Tioga/generic.c +254 -0
- data/split/Tioga/generic.h +236 -0
- data/split/Tioga/init.c +434 -320
- data/split/Tioga/lib/Creating_Paths.rb +11 -1
- data/split/Tioga/lib/FigMkr.rb +263 -65
- data/split/Tioga/lib/Legends.rb +4 -2
- data/split/Tioga/lib/Markers.rb +3 -2
- data/split/Tioga/lib/Special_Paths.rb +22 -23
- data/split/Tioga/lib/TeX_Text.rb +79 -1
- data/split/Tioga/lib/TexPreamble.rb +14 -0
- data/split/Tioga/lib/Utils.rb +5 -1
- data/split/Tioga/pdfs.h +7 -45
- data/split/Tioga/{axes.c → shared/axes.c} +210 -197
- data/split/Tioga/{makers.c → shared/makers.c} +442 -211
- data/split/Tioga/{pdf_font_dicts.c → shared/pdf_font_dicts.c} +0 -0
- data/split/Tioga/shared/pdfcolor.c +628 -0
- data/split/Tioga/shared/pdfcoords.c +443 -0
- data/split/Tioga/{pdffile.c → shared/pdffile.c} +56 -52
- data/split/Tioga/{pdfimage.c → shared/pdfimage.c} +103 -211
- data/split/Tioga/shared/pdfpath.c +766 -0
- data/split/Tioga/{pdftext.c → shared/pdftext.c} +121 -99
- data/split/Tioga/shared/texout.c +524 -0
- data/split/Tioga/wrappers.c +489 -0
- data/split/Tioga/wrappers.h +259 -0
- data/split/extconf.rb +4 -0
- data/split/mkmf2.rb +12 -1
- data/tests/benchmark_dvector_reads.rb +112 -0
- data/tests/tc_Dvector.rb +35 -3
- data/tests/tc_Function.rb +32 -0
- metadata +65 -52
- data/split/Tioga/pdfcolor.c +0 -486
- data/split/Tioga/pdfcoords.c +0 -523
- data/split/Tioga/pdfpath.c +0 -913
- data/split/Tioga/texout.c +0 -380
data/Tioga_README
CHANGED
@@ -20,16 +20,30 @@ This is the README for the Tioga kernel, version 1.6, March 17, 2007.
|
|
20
20
|
|
21
21
|
<< What's new >>
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
23
|
+
Version 1.7 adds an option in legends for markers without any line;
|
24
|
+
just call save_legend_info with 'line_type' => 'None' in addition to
|
25
|
+
the marker information. It is also now possible to give a 'legend' argument
|
26
|
+
to show_marker. The value of the arg can be either a legend dictionary
|
27
|
+
or simply the legend text in which case defaults will be supplied for
|
28
|
+
the rest. There is an example of this in samples/plots.rb
|
29
|
+
in the Legend_Outside figure.
|
30
|
+
|
31
|
+
It saw a very significant improvement in that you can now query
|
32
|
+
the exact size of a text typeset by LaTeX, with the function text_size. Please
|
33
|
+
have a look at its documentation, and at the Text_size and
|
34
|
+
Text_size_with_rotation samples in samples/figures/figures.rb.
|
35
|
+
|
36
|
+
The code base was quite moved around so as to facilitate work on a
|
37
|
+
Python version that would share as much code as possible with the Ruby one;
|
38
|
+
this should not bring user-visible changes (apart, maybe, from compilation
|
39
|
+
problems, but we hope not).
|
40
|
+
|
41
|
+
Some bug fixes, including potential stack overflows (unprotected
|
42
|
+
snprintfs), and some new methods of Function. Dvector.fancy_read has been
|
43
|
+
reimplemented in C and benchmarked: it should be around three times faster
|
44
|
+
than before.
|
45
|
+
|
46
|
+
Code should now compile cleanly with Ruby 1.9.
|
33
47
|
|
34
48
|
<< Quick Installation of Tioga >>
|
35
49
|
|
@@ -177,6 +191,17 @@ Bill Paxton
|
|
177
191
|
Here are the old release messages:
|
178
192
|
|
179
193
|
|
194
|
+
|
195
|
+
--------------------------
|
196
|
+
|
197
|
+
Version 1.6 adds numeric label "frequency" and "phase" attributes for
|
198
|
+
both axes. Previously Tioga assumed that every major tick mark got a numeric
|
199
|
+
label. Now the i'th major tick on the axis gets a label only if
|
200
|
+
mod(i+j,k)==0 where j is the phase and k is the frequency. The default
|
201
|
+
frequency is naturally 1 so that every major tick gets a label.
|
202
|
+
The full names for these attributes are xaxis_numeric_label_frequency,
|
203
|
+
xaxis_numeric_label_phase, and similar for yaxis.
|
204
|
+
|
180
205
|
--------------------------
|
181
206
|
|
182
207
|
Version 1.5 is mainly Vincent's work, so my part of this release message
|
data/split/Dvector/dvector.c
CHANGED
@@ -310,6 +310,23 @@ PRIVATE VALUE make_new_dvector(VALUE klass, long len, long capa) {
|
|
310
310
|
return ary;
|
311
311
|
}
|
312
312
|
|
313
|
+
/* Makes a Dvector with the given data. No additional capacity. */
|
314
|
+
PRIVATE VALUE make_dvector_from_data(VALUE klass, long len, double * data) {
|
315
|
+
VALUE ary = dvector_alloc(klass);
|
316
|
+
Dvector *d = Get_Dvector(ary);
|
317
|
+
if (len < 0) {
|
318
|
+
rb_raise(rb_eArgError, "negative dvector size (or size too big)");
|
319
|
+
}
|
320
|
+
d->len = len;
|
321
|
+
if (len == 0) len++;
|
322
|
+
d->ptr = ALLOC_N(double, len);
|
323
|
+
MEMCPY(d->ptr, data, double, len);
|
324
|
+
d->capa = len;
|
325
|
+
/* we set dirty to 0 */
|
326
|
+
d->dirty = 0;
|
327
|
+
return ary;
|
328
|
+
}
|
329
|
+
|
313
330
|
PRIVATE VALUE dvector_new2(long len, long capa) {
|
314
331
|
return make_new_dvector(cDvector, len, capa);
|
315
332
|
}
|
@@ -1430,7 +1447,7 @@ PRIVATE VALUE dvector_join(VALUE ary, VALUE sep) {
|
|
1430
1447
|
}
|
1431
1448
|
result = rb_str_buf_new(len);
|
1432
1449
|
for (i=0; i < d->len; i++) {
|
1433
|
-
|
1450
|
+
snprintf(buff,sizeof(buff), "%g", d->ptr[i]);
|
1434
1451
|
tmp = rb_str_new2(buff);
|
1435
1452
|
if (i > 0 && !NIL_P(sep)) rb_str_buf_append(result, sep);
|
1436
1453
|
rb_str_buf_append(result, tmp);
|
@@ -2097,19 +2114,12 @@ PRIVATE
|
|
2097
2114
|
VALUE dvector_replace(VALUE dest, VALUE orig) {
|
2098
2115
|
VALUE shared;
|
2099
2116
|
Dvector *org, *d;
|
2100
|
-
dvector_modify(dest);
|
2117
|
+
dvector_modify(dest); // take care of any sharing issues.
|
2101
2118
|
orig = dvector_to_dvector(orig); /* it might be some kind of Array rather than a Dvector */
|
2102
2119
|
if (dest == orig) return dest;
|
2103
2120
|
org = Get_Dvector(orig);
|
2104
2121
|
d = Get_Dvector(dest);
|
2105
|
-
if (d->ptr)
|
2106
|
-
if (0 && d->capa >= org->len && d->shared == Qnil) {
|
2107
|
-
d->len = org->len;
|
2108
|
-
MEMCPY(d->ptr, org->ptr, double, d->len);
|
2109
|
-
return dest;
|
2110
|
-
}
|
2111
|
-
free(d->ptr);
|
2112
|
-
}
|
2122
|
+
if (d->ptr) free(d->ptr); // we know it isn't shared because we did dvector_modify above
|
2113
2123
|
shared = dvector_make_shared(orig);
|
2114
2124
|
org = Get_Dvector(shared);
|
2115
2125
|
d->ptr = org->ptr;
|
@@ -4321,6 +4331,49 @@ VALUE dvector_div_bang(VALUE ary, VALUE arg) {
|
|
4321
4331
|
return dvector_apply_math_op2_bang(ary, arg, do_div);
|
4322
4332
|
}
|
4323
4333
|
|
4334
|
+
static char *fill_read_buffer(char **buff_ptr, int *len_ptr, FILE *file) {
|
4335
|
+
char *buff, *new_buff;
|
4336
|
+
buff = *buff_ptr;
|
4337
|
+
int len, i, max_tries, line_len;
|
4338
|
+
long filepos = ftell(file);
|
4339
|
+
if (filepos == -1) {
|
4340
|
+
printf("ftell failed\n");
|
4341
|
+
return NULL;
|
4342
|
+
}
|
4343
|
+
max_tries = 10;
|
4344
|
+
for (i = 0; i < max_tries; i++) {
|
4345
|
+
len = *len_ptr;
|
4346
|
+
buff[len-1] = '1'; // mark the last character position
|
4347
|
+
buff = fgets(buff, len, file);
|
4348
|
+
if (buff == NULL) return NULL; // end of file
|
4349
|
+
if (buff[len-1] != '\0') {
|
4350
|
+
if (0) {
|
4351
|
+
line_len = strlen(buff);
|
4352
|
+
printf("len %i line_len %i\n", len, line_len);
|
4353
|
+
if (line_len < 80) {
|
4354
|
+
printf("line buff contains: %s\n", buff);
|
4355
|
+
} else {
|
4356
|
+
printf("line buff ends with: %s\n", buff+line_len-80);
|
4357
|
+
}
|
4358
|
+
}
|
4359
|
+
return buff;
|
4360
|
+
}
|
4361
|
+
// ran out of room -- make buffer larger and try again
|
4362
|
+
len = 10*len + 100;
|
4363
|
+
//printf("fill_read_buffer ran out of room -- increase buffer len to %i and try again\n", len);
|
4364
|
+
*len_ptr = len;
|
4365
|
+
new_buff = (char *)realloc(buff, len);
|
4366
|
+
if (new_buff == NULL) break;
|
4367
|
+
buff = new_buff;
|
4368
|
+
*buff_ptr = buff;
|
4369
|
+
if (fseek(file, filepos, SEEK_SET) != 0) {
|
4370
|
+
printf("fseek failed\n");
|
4371
|
+
return NULL;
|
4372
|
+
}
|
4373
|
+
}
|
4374
|
+
return NULL;
|
4375
|
+
}
|
4376
|
+
|
4324
4377
|
PRIVATE
|
4325
4378
|
/*======================================================================*/
|
4326
4379
|
VALUE Read_Dvectors(char *filename, VALUE destinations, int first_row_of_file, int number_of_rows) {
|
@@ -4329,8 +4382,8 @@ VALUE Read_Dvectors(char *filename, VALUE destinations, int first_row_of_file, i
|
|
4329
4382
|
Dvector *d;
|
4330
4383
|
double v;
|
4331
4384
|
int last_row_of_file;
|
4332
|
-
|
4333
|
-
char buff
|
4385
|
+
int buff_len = 100;
|
4386
|
+
char *buff, *num_str, *pend, c, *cptr;
|
4334
4387
|
int num_cols = 0, i, row, col, buff_loc, skip = first_row_of_file - 1;
|
4335
4388
|
last_row_of_file = (number_of_rows == -1)? -1 : first_row_of_file + number_of_rows - 1;
|
4336
4389
|
if ((last_row_of_file != -1 && last_row_of_file < first_row_of_file) || filename == NULL) return false;
|
@@ -4355,15 +4408,21 @@ VALUE Read_Dvectors(char *filename, VALUE destinations, int first_row_of_file, i
|
|
4355
4408
|
if ((file=fopen(filename,"r")) == NULL) {
|
4356
4409
|
rb_raise(rb_eArgError, "ERROR: read cannot open %s", filename);
|
4357
4410
|
}
|
4411
|
+
buff = (char *)malloc(buff_len);
|
4412
|
+
if (buff == NULL) {
|
4413
|
+
fclose(file);
|
4414
|
+
rb_raise(rb_eArgError, "ERROR: allocation of read buffer failed");
|
4415
|
+
}
|
4358
4416
|
for (i = 0; i < skip; i++) { /* skip over initial lines */
|
4359
|
-
if (
|
4417
|
+
if (fill_read_buffer(&buff, &buff_len, file)==NULL) {
|
4360
4418
|
fclose(file);
|
4419
|
+
free(buff);
|
4361
4420
|
rb_raise(rb_eArgError, "ERROR: read reached end of file before reaching line %i in %s",
|
4362
4421
|
first_row_of_file, filename);
|
4363
4422
|
}
|
4364
4423
|
}
|
4365
4424
|
for (row = 0, i = first_row_of_file; last_row_of_file == -1 || i <= last_row_of_file; row++, i++) {
|
4366
|
-
if (
|
4425
|
+
if (fill_read_buffer(&buff, &buff_len, file)==NULL) break; /* have reached end of file */
|
4367
4426
|
if (destinations == Qnil) { /* create destinations */
|
4368
4427
|
buff_loc = 0;
|
4369
4428
|
while (true) {
|
@@ -4386,12 +4445,14 @@ VALUE Read_Dvectors(char *filename, VALUE destinations, int first_row_of_file, i
|
|
4386
4445
|
while (isspace(buff[buff_loc])) buff_loc++; /* skip leading blanks */
|
4387
4446
|
if (buff[buff_loc] == '\0') {
|
4388
4447
|
fclose(file);
|
4448
|
+
free(buff);
|
4389
4449
|
rb_raise(rb_eArgError, "read reached end of line looking for column %i in line %i of %s", col+1, i, filename);
|
4390
4450
|
}
|
4391
4451
|
num_str = buff+buff_loc;
|
4392
4452
|
while (isgraph(buff[buff_loc])) buff_loc++; /* include non-blanks */
|
4393
4453
|
if (buff[buff_loc] == '\0') {
|
4394
4454
|
fclose(file);
|
4455
|
+
free(buff);
|
4395
4456
|
rb_raise(rb_eArgError, "ERROR: read reached end of line looking for column %i in line %i of %s", col+1, i, filename);
|
4396
4457
|
}
|
4397
4458
|
col_obj = cols_ptr[col];
|
@@ -4410,6 +4471,7 @@ VALUE Read_Dvectors(char *filename, VALUE destinations, int first_row_of_file, i
|
|
4410
4471
|
v = strtod(num_str,&pend); *cptr = c; buff_loc = pend - buff;
|
4411
4472
|
} else {
|
4412
4473
|
fclose(file);
|
4474
|
+
free(buff);
|
4413
4475
|
pend[0] = 0;
|
4414
4476
|
rb_raise(rb_eArgError, "ERROR: unreadable value in file %s in line %i: %s", filename, i , buff+buff_loc);
|
4415
4477
|
}
|
@@ -4418,6 +4480,7 @@ VALUE Read_Dvectors(char *filename, VALUE destinations, int first_row_of_file, i
|
|
4418
4480
|
|
4419
4481
|
if (!is_okay_number(v)) {
|
4420
4482
|
fclose(file);
|
4483
|
+
free(buff);
|
4421
4484
|
rb_raise(rb_eArgError, "ERROR: bad value %g in line %i of %s -- %s", v, i, filename, num_str);
|
4422
4485
|
}
|
4423
4486
|
if (row >= d->capa)
|
@@ -4430,6 +4493,7 @@ VALUE Read_Dvectors(char *filename, VALUE destinations, int first_row_of_file, i
|
|
4430
4493
|
}
|
4431
4494
|
}
|
4432
4495
|
fclose(file);
|
4496
|
+
free(buff);
|
4433
4497
|
return destinations;
|
4434
4498
|
}
|
4435
4499
|
|
@@ -4467,8 +4531,8 @@ VALUE Read_Rows_of_Dvectors(char *filename, VALUE destinations, int first_row_of
|
|
4467
4531
|
VALUE row_obj, rows_obj, *rows_ptr = NULL;
|
4468
4532
|
Dvector *d;
|
4469
4533
|
double v, *row_data;
|
4470
|
-
|
4471
|
-
char buff
|
4534
|
+
int buff_len = 1000;
|
4535
|
+
char *buff, *num_str, *pend, c, *cptr;
|
4472
4536
|
int num_rows = 0, i, row, col, buff_loc, c_loc, skip = first_row_of_file - 1;
|
4473
4537
|
rows_obj = rb_Array(destinations);
|
4474
4538
|
num_rows = RARRAY(rows_obj)->len;
|
@@ -4489,16 +4553,23 @@ VALUE Read_Rows_of_Dvectors(char *filename, VALUE destinations, int first_row_of
|
|
4489
4553
|
if ((file=fopen(filename,"r")) == NULL) {
|
4490
4554
|
rb_raise(rb_eArgError, "ERROR: read_rows cannot open %s", filename);
|
4491
4555
|
}
|
4556
|
+
buff = (char *)malloc(buff_len);
|
4557
|
+
if (buff == NULL) {
|
4558
|
+
fclose(file);
|
4559
|
+
rb_raise(rb_eArgError, "ERROR: allocation of read buffer failed");
|
4560
|
+
}
|
4492
4561
|
for (i = 0; i < skip; i++) { /* skip over initial lines */
|
4493
|
-
if (
|
4562
|
+
if (fill_read_buffer(&buff, &buff_len, file)==NULL) {
|
4494
4563
|
fclose(file);
|
4564
|
+
free(buff);
|
4495
4565
|
rb_raise(rb_eArgError, "ERROR: read_rows reached end of file before reaching line %i in %s",
|
4496
4566
|
first_row_of_file, filename);
|
4497
4567
|
}
|
4498
4568
|
}
|
4499
4569
|
for (row = 0, i = first_row_of_file; row < num_rows; row++, i++) {
|
4500
|
-
if (
|
4570
|
+
if (fill_read_buffer(&buff, &buff_len, file)==NULL) {
|
4501
4571
|
fclose(file);
|
4572
|
+
free(buff);
|
4502
4573
|
rb_raise(rb_eArgError, "ERROR: read_rows reached end of file at line %i in %s", i, filename);
|
4503
4574
|
}
|
4504
4575
|
row_obj = rows_ptr[row];
|
@@ -4529,6 +4600,7 @@ VALUE Read_Rows_of_Dvectors(char *filename, VALUE destinations, int first_row_of
|
|
4529
4600
|
|
4530
4601
|
if (!is_okay_number(v)) {
|
4531
4602
|
fclose(file);
|
4603
|
+
free(buff);
|
4532
4604
|
rb_raise(rb_eArgError, "ERROR: bad value %g in line i% of file %s", v, i, filename);
|
4533
4605
|
}
|
4534
4606
|
if (col < d->capa) { row_data[col] = v; d->len = col+1; }
|
@@ -4544,6 +4616,7 @@ VALUE Read_Rows_of_Dvectors(char *filename, VALUE destinations, int first_row_of
|
|
4544
4616
|
}
|
4545
4617
|
}
|
4546
4618
|
fclose(file);
|
4619
|
+
free(buff);
|
4547
4620
|
return destinations;
|
4548
4621
|
}
|
4549
4622
|
|
@@ -4569,11 +4642,12 @@ VALUE dvector_read_rows(int argc, VALUE *argv, VALUE klass) {
|
|
4569
4642
|
return Read_Rows_of_Dvectors(StringValueCStr(argv[0]),argv[1],arg3);
|
4570
4643
|
klass = Qnil;
|
4571
4644
|
}
|
4645
|
+
|
4572
4646
|
PRIVATE
|
4573
4647
|
VALUE Read_Row(char *filename, int row, VALUE row_ary) {
|
4574
4648
|
FILE *file = NULL;
|
4575
|
-
|
4576
|
-
char buff
|
4649
|
+
int buff_len = 1000;
|
4650
|
+
char *buff, *num_str, *pend, c, *cptr;
|
4577
4651
|
int i, col, buff_loc;
|
4578
4652
|
double v;
|
4579
4653
|
if (row <= 0) {
|
@@ -4582,9 +4656,15 @@ VALUE Read_Row(char *filename, int row, VALUE row_ary) {
|
|
4582
4656
|
if (filename == NULL || (file=fopen(filename,"r")) == NULL) {
|
4583
4657
|
rb_raise(rb_eArgError, "ERROR: read_row cannot open %s", filename);
|
4584
4658
|
}
|
4659
|
+
buff = (char *)malloc(buff_len);
|
4660
|
+
if (buff == NULL) {
|
4661
|
+
fclose(file);
|
4662
|
+
rb_raise(rb_eArgError, "ERROR: allocation of read buffer failed");
|
4663
|
+
}
|
4585
4664
|
for (i = 0; i < row; i++) { /* read lines until reach desired row */
|
4586
|
-
if (
|
4665
|
+
if (fill_read_buffer(&buff, &buff_len, file)==NULL) {
|
4587
4666
|
fclose(file);
|
4667
|
+
free(buff);
|
4588
4668
|
rb_raise(rb_eArgError, "ERROR: read_row reached end of file before reaching line %i in %s",
|
4589
4669
|
row, filename);
|
4590
4670
|
}
|
@@ -4593,6 +4673,7 @@ VALUE Read_Row(char *filename, int row, VALUE row_ary) {
|
|
4593
4673
|
else if (is_a_dvector(row_ary)) dvector_clear(row_ary);
|
4594
4674
|
else {
|
4595
4675
|
fclose(file);
|
4676
|
+
free(buff);
|
4596
4677
|
rb_raise(rb_eArgError, "ERROR: destination for read_row must be a Dvector");
|
4597
4678
|
}
|
4598
4679
|
buff_loc = 0;
|
@@ -4614,6 +4695,7 @@ VALUE Read_Row(char *filename, int row, VALUE row_ary) {
|
|
4614
4695
|
v = strtod(num_str,&pend); *cptr = c; buff_loc = pend - buff;
|
4615
4696
|
} else {
|
4616
4697
|
fclose(file);
|
4698
|
+
free(buff);
|
4617
4699
|
pend[0] = 0;
|
4618
4700
|
rb_raise(rb_eArgError, "ERROR: unreadable value in file %s in line %i: %s", filename, i , buff+buff_loc);
|
4619
4701
|
}
|
@@ -4622,11 +4704,13 @@ VALUE Read_Row(char *filename, int row, VALUE row_ary) {
|
|
4622
4704
|
|
4623
4705
|
if (!is_okay_number(v)) {
|
4624
4706
|
fclose(file);
|
4707
|
+
free(buff);
|
4625
4708
|
rb_raise(rb_eArgError, "ERROR: bad value %g in line %i of file %s", v, i, filename);
|
4626
4709
|
}
|
4627
4710
|
Dvector_Store_Double(row_ary, col, v);
|
4628
4711
|
}
|
4629
4712
|
fclose(file);
|
4713
|
+
free(buff);
|
4630
4714
|
return row_ary;
|
4631
4715
|
}
|
4632
4716
|
|
@@ -5161,6 +5245,158 @@ static VALUE dvector_convolve(VALUE self, VALUE kernel, VALUE middle)
|
|
5161
5245
|
return retval;
|
5162
5246
|
}
|
5163
5247
|
|
5248
|
+
|
5249
|
+
/*
|
5250
|
+
:call-seq:
|
5251
|
+
Dvector.fast_fancy_read(stream, options) => Array_of_Dvectors
|
5252
|
+
|
5253
|
+
Reads data from an IO stream and separate it into columns of data
|
5254
|
+
according to the _options_, a hash holding the following elements
|
5255
|
+
(compulsory, but you can use FANCY_READ_DEFAULTS):
|
5256
|
+
* 'sep': a regular expression that separate the entries
|
5257
|
+
* 'comments': any line matching this will be skipped
|
5258
|
+
* 'skip_first': skips that many lines before reading anything
|
5259
|
+
* 'index_col': if true, the first column returned contains the
|
5260
|
+
number of the line read
|
5261
|
+
* 'remove_space': whether to remove spaces at the beginning of a line. *This
|
5262
|
+
option is currently not implemented !*
|
5263
|
+
* 'default': what to put when nothing was found but a number must be used
|
5264
|
+
|
5265
|
+
As a side note, the read time is highly non-linear, which suggests that
|
5266
|
+
the read is memory-allocation/copying-limited, at least for big files.
|
5267
|
+
Well, the read time is non-linear for
|
5268
|
+
|
5269
|
+
|
5270
|
+
An internal memory allocation with aggressive policy should solve that,
|
5271
|
+
that is, not using directly Dvectors (and it would be way faster to store
|
5272
|
+
anyway).
|
5273
|
+
*/
|
5274
|
+
static VALUE dvector_fast_fancy_read(VALUE self, VALUE stream, VALUE options)
|
5275
|
+
{
|
5276
|
+
/* First, we read up options: */
|
5277
|
+
double def = rb_num2dbl(rb_hash_aref(options,
|
5278
|
+
rb_str_new2("default")));
|
5279
|
+
int remove_space = RTEST(rb_hash_aref(options,
|
5280
|
+
rb_str_new2("remove_space")));
|
5281
|
+
int index_col = RTEST(rb_hash_aref(options,
|
5282
|
+
rb_str_new2("index_col")));
|
5283
|
+
long skip_first = FIX2LONG(rb_hash_aref(options,
|
5284
|
+
rb_str_new2("skip_first")));
|
5285
|
+
VALUE sep = rb_hash_aref(options, rb_str_new2("sep"));
|
5286
|
+
VALUE comments = rb_hash_aref(options, rb_str_new2("comments"));
|
5287
|
+
|
5288
|
+
/* Then, some various variables: */
|
5289
|
+
VALUE line;
|
5290
|
+
|
5291
|
+
ID chomp_id = rb_intern("chomp!");
|
5292
|
+
ID gets_id = rb_intern("gets");
|
5293
|
+
long line_number = 0;
|
5294
|
+
|
5295
|
+
/*
|
5296
|
+
Now come the fun part - rudimentary vectors management
|
5297
|
+
*/
|
5298
|
+
int nb_vectors = 0; /* The number of vectors currently created */
|
5299
|
+
int current_size = 10; /* The number of slots available */
|
5300
|
+
double ** vectors = ALLOC_N(double *, current_size);
|
5301
|
+
long index = 0; /* The current index in the vectors */
|
5302
|
+
int allocated_size = 5004; /* The size available in the vectors */
|
5303
|
+
|
5304
|
+
|
5305
|
+
int i;
|
5306
|
+
|
5307
|
+
/* The return value */
|
5308
|
+
VALUE ary;
|
5309
|
+
|
5310
|
+
/* We use a real gets so we can also rely on StringIO, for instance */
|
5311
|
+
while(RTEST(line = rb_funcall(stream, gets_id, 0))) {
|
5312
|
+
VALUE pre, post, match;
|
5313
|
+
const char * line_ptr;
|
5314
|
+
int col = 0;
|
5315
|
+
line_number++;
|
5316
|
+
/* Whether we should skip the line... */
|
5317
|
+
if(skip_first >= line_number)
|
5318
|
+
continue;
|
5319
|
+
|
5320
|
+
/* We check for a blank line using isspace: */
|
5321
|
+
line_ptr = StringValueCStr(line);
|
5322
|
+
while(line_ptr && *line_ptr) {
|
5323
|
+
if(! isspace(*line_ptr))
|
5324
|
+
break;
|
5325
|
+
line_ptr++;
|
5326
|
+
}
|
5327
|
+
if(! *line_ptr)
|
5328
|
+
continue; /* We found a blank line */
|
5329
|
+
if(remove_space) /* We replace the contents of the line */
|
5330
|
+
line = rb_str_new2(line_ptr);
|
5331
|
+
|
5332
|
+
/* ... or a comment line */
|
5333
|
+
if(RTEST(comments) && RTEST(rb_reg_match(comments, line)))
|
5334
|
+
continue;
|
5335
|
+
|
5336
|
+
/* Then, we remove the newline: */
|
5337
|
+
post = line;
|
5338
|
+
rb_funcall(post, chomp_id, 0);
|
5339
|
+
|
5340
|
+
/* We iterate over the different portions between
|
5341
|
+
matches
|
5342
|
+
*/
|
5343
|
+
while(RTEST(post)) {
|
5344
|
+
const char * a;
|
5345
|
+
char * b;
|
5346
|
+
if(RTEST(rb_reg_match(sep, post))) {
|
5347
|
+
match = rb_gv_get("$~");
|
5348
|
+
pre = rb_reg_match_pre(match);
|
5349
|
+
post = rb_reg_match_post(match);
|
5350
|
+
}
|
5351
|
+
else {
|
5352
|
+
pre = post;
|
5353
|
+
post = Qnil;
|
5354
|
+
}
|
5355
|
+
a = StringValueCStr(pre);
|
5356
|
+
double c = strtod(a, &b);
|
5357
|
+
if(b == a)
|
5358
|
+
c = def;
|
5359
|
+
if(col >= nb_vectors) {
|
5360
|
+
nb_vectors++;
|
5361
|
+
/* We need to create a new vector */
|
5362
|
+
if(col >= current_size) { /* Increase the available size */
|
5363
|
+
current_size += 5;
|
5364
|
+
REALLOC_N(vectors, double * , current_size);
|
5365
|
+
}
|
5366
|
+
|
5367
|
+
double * vals = vectors[col] = ALLOC_N(double, allocated_size);
|
5368
|
+
/* Filling it with the default value */
|
5369
|
+
for(i = 0; i < index; i++) {
|
5370
|
+
vals[i] = def;
|
5371
|
+
}
|
5372
|
+
}
|
5373
|
+
vectors[col][index] = c;
|
5374
|
+
col++;
|
5375
|
+
}
|
5376
|
+
/* Now, we finish the line */
|
5377
|
+
for(; col < nb_vectors; col++)
|
5378
|
+
vectors[col][index] = def;
|
5379
|
+
index++;
|
5380
|
+
/* Now, we reallocate memory if necessary */
|
5381
|
+
if(index >= allocated_size) {
|
5382
|
+
allocated_size *= 2; /* We double the size */
|
5383
|
+
for(col = 0; col < nb_vectors; col++)
|
5384
|
+
REALLOC_N(vectors[col], double, allocated_size);
|
5385
|
+
}
|
5386
|
+
}
|
5387
|
+
/* Now, we make up the array */
|
5388
|
+
ary = rb_ary_new();
|
5389
|
+
for(i = 0; i < nb_vectors; i++) {
|
5390
|
+
/* We create a vector */
|
5391
|
+
rb_ary_store(ary, i, make_dvector_from_data(cDvector, index, vectors[i]));
|
5392
|
+
/* And free the memory */
|
5393
|
+
free(vectors[i]);
|
5394
|
+
}
|
5395
|
+
free(vectors);
|
5396
|
+
return ary;
|
5397
|
+
}
|
5398
|
+
|
5399
|
+
|
5164
5400
|
/*
|
5165
5401
|
* Document-class: Dobjects::Dvector
|
5166
5402
|
*
|
@@ -5236,7 +5472,8 @@ void Init_Dvector() {
|
|
5236
5472
|
rb_define_singleton_method(cDvector, "is_a_dvector", dvector_is_a_dvector, 1);
|
5237
5473
|
|
5238
5474
|
|
5239
|
-
rb_define_method(cDvector, "make_bezier_control_points_for_cubic_in_x",
|
5475
|
+
rb_define_method(cDvector, "make_bezier_control_points_for_cubic_in_x",
|
5476
|
+
dvector_make_bezier_control_points_for_cubic_in_x, 6);
|
5240
5477
|
|
5241
5478
|
rb_define_method(cDvector, "initialize", dvector_initialize, -1);
|
5242
5479
|
rb_define_method(cDvector, "initialize_copy", dvector_replace, 1);
|
@@ -5475,6 +5712,11 @@ void Init_Dvector() {
|
|
5475
5712
|
/* simple convolution */
|
5476
5713
|
rb_define_method(cDvector, "convolve", dvector_convolve, 2);
|
5477
5714
|
|
5715
|
+
/* Fast fancy read: */
|
5716
|
+
rb_define_singleton_method(cDvector, "fast_fancy_read",
|
5717
|
+
dvector_fast_fancy_read, 2);
|
5718
|
+
|
5719
|
+
|
5478
5720
|
dvector_output_fs = Qnil;
|
5479
5721
|
rb_global_variable(&dvector_output_fs);
|
5480
5722
|
dvector_output_fs = rb_str_new2(" ");
|