tioga 1.6 → 1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/Tioga_README +35 -10
  2. data/split/Dvector/dvector.c +264 -22
  3. data/split/Dvector/lib/Dvector_extras.rb +30 -2
  4. data/split/Flate/extconf.rb +1 -1
  5. data/split/Function/function.c +112 -2
  6. data/split/Tioga/figures.c +76 -77
  7. data/split/Tioga/figures.h +375 -490
  8. data/split/Tioga/generic.c +254 -0
  9. data/split/Tioga/generic.h +236 -0
  10. data/split/Tioga/init.c +434 -320
  11. data/split/Tioga/lib/Creating_Paths.rb +11 -1
  12. data/split/Tioga/lib/FigMkr.rb +263 -65
  13. data/split/Tioga/lib/Legends.rb +4 -2
  14. data/split/Tioga/lib/Markers.rb +3 -2
  15. data/split/Tioga/lib/Special_Paths.rb +22 -23
  16. data/split/Tioga/lib/TeX_Text.rb +79 -1
  17. data/split/Tioga/lib/TexPreamble.rb +14 -0
  18. data/split/Tioga/lib/Utils.rb +5 -1
  19. data/split/Tioga/pdfs.h +7 -45
  20. data/split/Tioga/{axes.c → shared/axes.c} +210 -197
  21. data/split/Tioga/{makers.c → shared/makers.c} +442 -211
  22. data/split/Tioga/{pdf_font_dicts.c → shared/pdf_font_dicts.c} +0 -0
  23. data/split/Tioga/shared/pdfcolor.c +628 -0
  24. data/split/Tioga/shared/pdfcoords.c +443 -0
  25. data/split/Tioga/{pdffile.c → shared/pdffile.c} +56 -52
  26. data/split/Tioga/{pdfimage.c → shared/pdfimage.c} +103 -211
  27. data/split/Tioga/shared/pdfpath.c +766 -0
  28. data/split/Tioga/{pdftext.c → shared/pdftext.c} +121 -99
  29. data/split/Tioga/shared/texout.c +524 -0
  30. data/split/Tioga/wrappers.c +489 -0
  31. data/split/Tioga/wrappers.h +259 -0
  32. data/split/extconf.rb +4 -0
  33. data/split/mkmf2.rb +12 -1
  34. data/tests/benchmark_dvector_reads.rb +112 -0
  35. data/tests/tc_Dvector.rb +35 -3
  36. data/tests/tc_Function.rb +32 -0
  37. metadata +65 -52
  38. data/split/Tioga/pdfcolor.c +0 -486
  39. data/split/Tioga/pdfcoords.c +0 -523
  40. data/split/Tioga/pdfpath.c +0 -913
  41. data/split/Tioga/texout.c +0 -380
@@ -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
- Version 1.6 adds numeric label "frequency" and "phase" attributes for
24
- both axes. Previously Tioga assumed that every major tick mark got a numeric
25
- label. Now the i'th major tick on the axis gets a label only if
26
- mod(i+j,k)==0 where j is the phase and k is the frequency. The default
27
- frequency is naturally 1 so that every major tick gets a label.
28
- The full names for these attributes are xaxis_numeric_label_frequency,
29
- xaxis_numeric_label_phase, and similar for yaxis.
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
@@ -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
- sprintf(buff, "%g", d->ptr[i]);
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
- const int buff_len = 10000;
4333
- char buff[buff_len], *num_str, *pend, c, *cptr;
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 (fgets(buff, buff_len, file)==NULL) {
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 (fgets(buff, buff_len, file)==NULL) break; /* have reached end of file */
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
- const int buff_len = 10000;
4471
- char buff[buff_len], *num_str, *pend, c, *cptr;
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 (fgets(buff, buff_len, file)==NULL) {
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 (fgets(buff, buff_len, file)==NULL) {
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
- const int buff_len = 10000;
4576
- char buff[buff_len], *num_str, *pend, c, *cptr;
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 (fgets(buff, buff_len, file)==NULL) {
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", dvector_make_bezier_control_points_for_cubic_in_x, 6);
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(" ");