tioga 1.6 → 1.7
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.
- 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(" ");
|