Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
uvahotspot
GitHub Repository: uvahotspot/HotSpot
Path: blob/master/util.c
612 views
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <math.h>
4
#include <string.h>
5
#ifdef _MSC_VER
6
#define strcasecmp _stricmp
7
#define strncasecmp _strnicmp
8
#else
9
#include <strings.h>
10
#endif
11
#include <assert.h>
12
13
#include "util.h"
14
15
#define SWAP(a,b) {temp=(a); (a)=(b); (b)=temp;}
16
17
int eq(double x, double y)
18
{
19
return (fabs(x-y) < DELTA);
20
}
21
22
int le(double x, double y)
23
{
24
return ((x < y) || eq(x,y));
25
}
26
27
int ge(double x, double y)
28
{
29
return ((x > y) || eq(x,y));
30
}
31
32
void fatal(char *s)
33
{
34
fprintf(stderr, "error: %s", s);
35
exit(1);
36
}
37
38
void warning(char *s)
39
{
40
fprintf(stderr, "warning: %s", s);
41
}
42
43
void swap_ival (int *a, int *b)
44
{
45
int t = *a;
46
*a = *b;
47
*b = t;
48
}
49
50
void swap_dval (double *a, double *b)
51
{
52
double t = *a;
53
*a = *b;
54
*b = t;
55
}
56
57
int tolerant_ceil(double val)
58
{
59
double nearest = floor(val+0.5);
60
/* numbers close to integers */
61
if (eq(val, nearest))
62
return ((int) nearest);
63
/* all others */
64
else
65
return ((int) ceil(val));
66
}
67
68
int tolerant_floor(double val)
69
{
70
double nearest = floor(val+0.5);
71
/* numbers close to integers */
72
if (eq(val, nearest))
73
return ((int) nearest);
74
/* all others */
75
else
76
return ((int) floor(val));
77
}
78
79
double *dvector(int n)
80
{
81
double *v;
82
83
v=(double *)calloc(n, sizeof(double));
84
if (!v) fatal("allocation failure in dvector()\n");
85
86
return v;
87
}
88
89
void free_dvector(double *v)
90
{
91
free(v);
92
}
93
94
void dump_dvector (double *v, int n)
95
{
96
int i;
97
for (i=0; i < n; i++)
98
fprintf(stdout, "%.5f\t", v[i]);
99
fprintf(stdout, "\n");
100
}
101
102
void copy_dvector (double *dst, double *src, int n)
103
{
104
memmove(dst, src, sizeof(double) * n);
105
}
106
107
void zero_dvector (double *v, int n)
108
{
109
memset(v, 0, sizeof(double) * n);
110
}
111
112
/* sum of the elements */
113
double sum_dvector (double *v, int n)
114
{
115
double sum = 0;
116
int i;
117
for(i=0; i < n; i++)
118
sum += v[i];
119
return sum;
120
}
121
122
int *ivector(int n)
123
{
124
int *v;
125
126
v = (int *)calloc(n, sizeof(int));
127
if (!v) fatal("allocation failure in ivector()\n");
128
129
return v;
130
}
131
132
void free_ivector(int *v)
133
{
134
free(v);
135
}
136
137
void dump_ivector (int *v, int n)
138
{
139
int i;
140
for (i=0; i < n; i++)
141
fprintf(stdout, "%d\t", v[i]);
142
fprintf(stdout, "\n\n");
143
}
144
145
void copy_ivector (int *dst, int *src, int n)
146
{
147
memmove(dst, src, sizeof(int) * n);
148
}
149
150
void zero_ivector (int *v, int n)
151
{
152
memset(v, 0, sizeof(int) * n);
153
}
154
155
/*
156
* Thanks to Greg Link from Penn State University
157
* for these memory allocators/deallocators
158
*/
159
double **dmatrix(int nr, int nc)
160
{
161
int i;
162
double **m;
163
164
m = (double **) calloc (nr, sizeof(double *));
165
assert(m != NULL);
166
m[0] = (double *) calloc (nr * nc, sizeof(double));
167
assert(m[0] != NULL);
168
169
for (i = 1; i < nr; i++)
170
m[i] = m[0] + nc * i;
171
172
return m;
173
}
174
175
void free_dmatrix(double **m)
176
{
177
free(m[0]);
178
free(m);
179
}
180
181
int **imatrix(int nr, int nc)
182
{
183
int i;
184
int **m;
185
186
m = (int **) calloc (nr, sizeof(int *));
187
assert(m != NULL);
188
m[0] = (int *) calloc (nr * nc, sizeof(int));
189
assert(m[0] != NULL);
190
191
for (i = 1; i < nr; i++)
192
m[i] = m[0] + nc * i;
193
194
return m;
195
}
196
197
void free_imatrix(int **m)
198
{
199
free(m[0]);
200
free(m);
201
}
202
203
void dump_dmatrix (double **m, int nr, int nc)
204
{
205
int i;
206
for (i=0; i < nr; i++)
207
dump_dvector(m[i], nc);
208
fprintf(stdout, "\n");
209
}
210
211
void copy_dmatrix (double **dst, double **src, int nr, int nc)
212
{
213
memmove(dst[0], src[0], sizeof(double) * nr * nc);
214
}
215
216
void zero_dmatrix(double **m, int nr, int nc)
217
{
218
memset(m[0], 0, sizeof(double) * nr * nc);
219
}
220
221
void resize_dmatrix(double **m, int nr, int nc)
222
{
223
int i;
224
for (i = 1; i < nr; i++)
225
m[i] = m[0] + nc * i;
226
}
227
228
/* allocate 3-d matrix with 'nr' rows, 'nc' cols,
229
* 'nl' layers and a tail of 'xtra' elements
230
*/
231
double ***dcuboid_tail(int nr, int nc, int nl, int xtra)
232
{
233
int i, j;
234
double ***m;
235
236
/* 1-d array of pointers to the rows of the 2-d array below */
237
m = (double ***) calloc (nl, sizeof(double **));
238
assert(m != NULL);
239
/* 2-d array of pointers denoting (layer, row) */
240
m[0] = (double **) calloc (nl * nr, sizeof(double *));
241
assert(m[0] != NULL);
242
/* the actual 3-d data array */
243
m[0][0] = (double *) calloc (nl * nr * nc + xtra, sizeof(double));
244
assert(m[0][0] != NULL);
245
246
/* remaining pointers of the 1-d pointer array */
247
for (i = 1; i < nl; i++)
248
m[i] = m[0] + nr * i;
249
250
/* remaining pointers of the 2-d pointer array */
251
for (i = 0; i < nl; i++)
252
for (j = 0; j < nr; j++)
253
/* to reach the jth row in the ith layer,
254
* one has to cross i layers i.e., i*(nr*nc)
255
* values first and then j rows i.e., j*nc
256
* values next
257
*/
258
m[i][j] = m[0][0] + (nr * nc) * i + nc * j;
259
260
return m;
261
}
262
263
void free_dcuboid(double ***m)
264
{
265
free(m[0][0]);
266
free(m[0]);
267
free(m);
268
}
269
270
/* mirror the lower triangle to make 'm' fully symmetric */
271
void mirror_dmatrix(double **m, int n)
272
{
273
int i, j;
274
for(i=0; i < n; i++)
275
for(j=0; j < i; j++)
276
m[j][i] = m[i][j];
277
}
278
279
void dump_imatrix (int **m, int nr, int nc)
280
{
281
int i;
282
for (i=0; i < nr; i++)
283
dump_ivector(m[i], nc);
284
fprintf(stdout, "\n");
285
}
286
287
void copy_imatrix (int **dst, int **src, int nr, int nc)
288
{
289
memmove(dst[0], src[0], sizeof(int) * nr * nc);
290
}
291
292
void resize_imatrix(int **m, int nr, int nc)
293
{
294
int i;
295
for (i = 1; i < nr; i++)
296
m[i] = m[0] + nc * i;
297
}
298
299
/* initialize random number generator */
300
void init_rand(void)
301
{
302
srand(RAND_SEED);
303
}
304
305
/* random number within the range [0, max-1] */
306
int rand_upto(int max)
307
{
308
return (int) (max * (double) rand() / (RAND_MAX+1.0));
309
}
310
311
/* random number in the range [0, 1) */
312
double rand_fraction(void)
313
{
314
return ((double) rand() / (RAND_MAX+1.0));
315
}
316
317
/*
318
* reads tab-separated name-value pairs from file into
319
* a table of size max_entries and returns the number
320
* of entries read successfully
321
*/
322
int read_str_pairs(str_pair *table, int max_entries, char *file)
323
{
324
int i=0;
325
char str[LINE_SIZE], copy[LINE_SIZE];
326
char name[STR_SIZE];
327
char *ptr;
328
FILE *fp = fopen (file, "r");
329
if (!fp) {
330
sprintf (str,"error: %s could not be opened for reading\n", file);
331
fatal(str);
332
}
333
while(i < max_entries) {
334
fgets(str, LINE_SIZE, fp);
335
if (feof(fp))
336
break;
337
strcpy(copy, str);
338
339
/* ignore comments and empty lines */
340
ptr = strtok(str, " \r\t\n");
341
if (!ptr || ptr[0] == '#')
342
continue;
343
344
if ((sscanf(copy, "%s%s", name, table[i].value) != 2) || (name[0] != '-'))
345
fatal("invalid file format\n");
346
/* ignore the leading "-" */
347
strcpy(table[i].name, &name[1]);
348
i++;
349
}
350
fclose(fp);
351
return i;
352
}
353
354
/*
355
* same as above but from command line instead of a file. the command
356
* line is of the form <prog_name> <name-value pairs> where
357
* <name-value pairs> is of the form -<variable> <value>
358
*/
359
int parse_cmdline(str_pair *table, int max_entries, int argc, char **argv)
360
{
361
int i, count;
362
for (i=1, count=0; i < argc && count < max_entries; i++) {
363
if (i % 2) { /* variable name */
364
if (argv[i][0] != '-')
365
fatal("invalid command line. check usage\n");
366
/* ignore the leading "-" */
367
strncpy(table[count].name, &argv[i][1], STR_SIZE-1);
368
table[count].name[STR_SIZE-1] = '\0';
369
} else { /* value */
370
strncpy(table[count].value, argv[i], STR_SIZE-1);
371
table[count].value[STR_SIZE-1] = '\0';
372
count++;
373
}
374
}
375
return count;
376
}
377
378
/* append the table onto a file */
379
void dump_str_pairs(str_pair *table, int size, char *file, char *prefix)
380
{
381
int i;
382
char str[STR_SIZE];
383
FILE *fp = fopen (file, "w");
384
if (!fp) {
385
sprintf (str,"error: %s could not be opened for writing\n", file);
386
fatal(str);
387
}
388
for(i=0; i < size; i++)
389
fprintf(fp, "%s%s\t%s\n", prefix, table[i].name, table[i].value);
390
fclose(fp);
391
}
392
393
/* table lookup for a name */
394
int get_str_index(str_pair *table, int size, char *str)
395
{
396
int i;
397
398
if (!table)
399
fatal("null pointer in get_str_index\n");
400
401
for (i = 0; i < size; i++)
402
if (!strcasecmp(str, table[i].name))
403
return i;
404
return -1;
405
}
406
407
/* delete entry at 'at' */
408
void delete_entry(str_pair *table, int size, int at)
409
{
410
int i;
411
/*
412
* overwrite this entry using the next and
413
* shift all later entries once
414
*/
415
for (i=at+1; i < size; i++) {
416
strcpy(table[i-1].name, table[i].name);
417
strcpy(table[i-1].value, table[i].value);
418
}
419
}
420
421
/*
422
* remove duplicate names in the table - the entries later
423
* in the table are discarded. returns the new size of the
424
* table
425
*/
426
int str_pairs_remove_duplicates(str_pair *table, int size)
427
{
428
int i, j;
429
430
for(i=0; i < size-1; i++)
431
for(j=i+1; j < size; j++)
432
if (!strcasecmp(table[i].name, table[j].name)) {
433
delete_entry(table, size, j);
434
size--;
435
j--;
436
}
437
return size;
438
}
439
440
/* debug */
441
void print_str_pairs(str_pair *table, int size)
442
{
443
int i;
444
fprintf(stdout, "printing string table\n");
445
for (i=0; i < size; i++)
446
fprintf(stdout, "%s\t%s\n", table[i].name, table[i].value);
447
}
448
449
/*
450
* binary search a sorted double array 'arr' of size 'n'. if found,
451
* the 'loc' pointer has the address of 'ele' and the return
452
* value is TRUE. otherwise, the return value is FALSE and 'loc'
453
* points to the 'should have been' location
454
*/
455
int bsearch_double(double *arr, int n, double ele, double **loc)
456
{
457
if(n < 0)
458
fatal("wrong index in binary search\n");
459
460
if(n == 0) {
461
*loc = arr;
462
return FALSE;
463
}
464
465
if(eq(arr[n/2], ele)) {
466
*loc = &arr[n/2];
467
return TRUE;
468
} else if (arr[n/2] < ele) {
469
return bsearch_double(&arr[n/2+1], (n-1)/2, ele, loc);
470
} else
471
return bsearch_double(arr, n/2, ele, loc);
472
473
}
474
475
/*
476
* binary search and insert an element into a partially sorted
477
* double array if not already present. returns FALSE if present
478
*/
479
int bsearch_insert_double(double *arr, int n, double ele)
480
{
481
double *loc;
482
int i;
483
484
/* element found - nothing more left to do */
485
if (bsearch_double(arr, n, ele, &loc))
486
return FALSE;
487
else {
488
for(i=n-1; i >= (loc-arr); i--)
489
arr[i+1] = arr[i];
490
arr[loc-arr] = ele;
491
}
492
return TRUE;
493
}
494
495
/* search if an array contains a value
496
* return the index if so and -1 otherwise
497
*/
498
int contains(int *array, int size, int value)
499
{
500
int i;
501
for(i = 0; i < size; i++)
502
{
503
if(array[i] == value)
504
return i;
505
}
506
507
return -1;
508
}
509
510
/*
511
* population count of an 8-bit integer - using pointers from
512
* http://aggregate.org/MAGIC/
513
*/
514
unsigned int ones8(register unsigned char n)
515
{
516
/* group the bits in two and compute the no. of 1's within a group
517
* this works because 00->00, 01->01, 10->01, 11->10 or
518
* n = n - (n >> 1). the 0x55 masking prevents bits flowing across
519
* group boundary
520
*/
521
n -= ((n >> 1) & 0x55);
522
/* add the 2-bit sums into nibbles */
523
n = ((n & 0x33) + ((n >> 2) & 0x33));
524
/* add both the nibbles */
525
n = ((n + (n >> 4)) & 0x0F);
526
return n;
527
}
528
529
/*
530
* find the number of non-empty, non-comment lines
531
* in a file open for reading
532
*/
533
int count_significant_lines(FILE *fp)
534
{
535
char str[LINE_SIZE], *ptr;
536
int count = 0;
537
538
fseek(fp, 0, SEEK_SET);
539
while(!feof(fp)) {
540
fgets(str, LINE_SIZE, fp);
541
if (feof(fp))
542
break;
543
544
/* ignore comments and empty lines */
545
ptr = strtok(str, " \r\t\n");
546
if (!ptr || ptr[0] == '#')
547
continue;
548
549
count++;
550
}
551
return count;
552
}
553
554
/* Ke's code: Coo2CSC */
555
struct coo_elem
556
{
557
int x;
558
int y;
559
double val;
560
};
561
562
int c2c_cmp( const void *a , const void *b )
563
{
564
struct coo_elem *c = (struct coo_elem *)a;
565
struct coo_elem *d = (struct coo_elem *)b;
566
if(c->y != d->y) return c->y - d->y;
567
else return c->x - d->x;
568
}
569
570
int coo2csc(int size, int nnz,
571
int *cooX, int *cooY, double *cooV, // input COO array
572
int *cscRowInd, int *cscColPtr, double *cscV) //output CSC array
573
{
574
int i, j;
575
int prev_x, prev_y;
576
// Init struct array
577
struct coo_elem *cooArray;
578
cooArray = (struct coo_elem *) calloc (nnz, sizeof(struct coo_elem));
579
580
// Copy in
581
for (i =0; i <nnz; i++) {
582
cooArray[i].x = cooX[i];
583
cooArray[i].y = cooY[i];
584
cooArray[i].val = cooV[i];
585
}
586
587
// Sort in col major
588
qsort(cooArray, nnz, sizeof(cooArray[0]), c2c_cmp);
589
590
// Copy out, check duplicate
591
j = -1;
592
prev_x = -1;
593
prev_y = -1;
594
for (i =0; i <nnz; i++) {
595
cscRowInd[i]=cooArray[i].x;
596
cscV[i]=cooArray[i].val;
597
while(j<cooArray[i].y){
598
j++;
599
cscColPtr[j]=i;
600
}
601
if((cooArray[i].x == prev_x) &&
602
(cooArray[i].y == prev_y))
603
printf("Warning: Duplicate elements in Matrix!\n");
604
605
prev_x = cooArray[i].x;
606
prev_y = cooArray[i].y;
607
}
608
cscColPtr[j+1]=i;
609
610
free(cooArray);
611
612
return 1;
613
}
614
615
/*
616
* Gauss-Jordan elimination with full pivoting
617
* Taken from Numerical Recipes in C
618
* gaussj is written assuming that b is a vector, but it is trivial to instead
619
* make b an nxm matrix in order to solve Ax=b for m different values of b
620
*/
621
void gaussj(double **a, int n, double *b) {
622
int *indxc, *indxr, *ipiv;
623
int i, icol, irow, j, k, l, ll;
624
double big, dum, pivinv, temp;
625
626
indxc = calloc(n, sizeof(int));
627
indxr = calloc(n, sizeof(int));
628
ipiv = calloc(n, sizeof(int));
629
630
// Main Loop
631
for(i = 0; i < n; i++) {
632
big = 0.0;
633
634
// Search for a pivot element (choose the largest)
635
for(j = 0; j < n; j++) {
636
if (ipiv[j] != 1)
637
for(k = 0; k < n; k++) {
638
if(ipiv[k] == 0) {
639
if(fabs(a[j][k]) >= big) {
640
big = fabs(a[j][k]);
641
irow = j;
642
icol = k;
643
}
644
}
645
}
646
}
647
++(ipiv[icol]);
648
649
/*
650
* We've found the pivot, so we interchange rows if necessary to put
651
* the pivot on the diagonal
652
* indxc[i] = the column of the ith pivot element
653
* indxr[i] = the row in which that pivot element was originally located
654
* if indxr[i] != indxc[i], there is an implied column intercahnge
655
*/
656
if(irow != icol) {
657
for(l = 0; l < n; l++)
658
SWAP(a[irow][l], a[icol][l])
659
SWAP(b[irow], b[icol])
660
}
661
662
indxr[i] = irow;
663
indxc[i] = icol;
664
if(a[icol][icol] == 0.0)
665
fatal("gaussj: Singular Pressure Matrix\n");
666
667
pivinv = 1.0 / a[icol][icol];
668
a[icol][icol] = 1.0;
669
670
// Divide the pivot row by the pivot element
671
for(l = 0; l < n; l++)
672
a[icol][l] *= pivinv;
673
b[icol] *= pivinv;
674
675
// Reduce all rows except the row containing the pivot
676
for(ll = 0; ll < n; ll++) {
677
if(ll != icol) {
678
dum = a[ll][icol];
679
a[ll][icol] = 0.0;
680
for(l = 0; l < n; l++)
681
a[ll][l] -= a[icol][l] * dum;
682
b[ll] -= b[icol] * dum;
683
}
684
}
685
} // end of Main Loop
686
687
// Put columns back in original order
688
for(l = n-1; l >= 0; l--) {
689
if(indxr[l] != indxc[l]) {
690
for(k = 1; k < n; k++) {
691
SWAP(a[k][indxr[l]], a[k][indxc[l]]);
692
}
693
}
694
}
695
696
free(ipiv);
697
free(indxr);
698
free(indxc);
699
}
700
701
#if SUPERLU > 0
702
/*
703
* computes A = c*diag + A
704
* NOTE: Assumes that A contains only nonzero elements on its diagonal
705
*/
706
int diagonal_add_SparseMatrix(double c, diagonal_matrix_t *diag, SuperMatrix *A) {
707
NCformat *Astore;
708
int i, j;
709
int n;
710
double *a;
711
int *asub, *xa;
712
int flag = 1;
713
714
Astore = A->Store;
715
n = A->ncol;
716
a = Astore->nzval;
717
asub = Astore->rowind;
718
xa = Astore->colptr;
719
720
double *diag_vals = diag->vals;
721
722
for(i=0; i<n; i++){
723
flag = 1;
724
j = xa[i];
725
while(j<xa[i+1]){
726
if(asub[j] == i){
727
a[j] += c*diag_vals[i];
728
flag = 0;
729
fprintf(stderr, "A[%d] = %e\n", j, a[j]);
730
}
731
j++;
732
}
733
if(flag)
734
fatal("Matrix missing diagonal element! Cannot support that yet\n");
735
}
736
return 1;
737
}
738
739
/*
740
* computes vector = c*diag*vector
741
*/
742
int diagonal_mul_vector(double c, diagonal_matrix_t *diag, double **vector) {
743
int i, n;
744
double *diag_vals;
745
746
n = diag->n;
747
diag_vals = diag->vals;
748
749
for(i = 0; i < n; i++) {
750
(*vector)[i] *= c*diag_vals[i];
751
}
752
753
return 1;
754
}
755
756
/*
757
* computes vector2 += vector1
758
*/
759
int vector_add_vector(int n, double c1, double *vector1, double c2, double *vector2) {
760
int i;
761
762
for(i = 0; i < n; i++) {
763
//fprintf(stderr, "vector2[%d] = vector1[%d] + vector[%d] = %e + %e = ", i, i, i, vector1[i], vector2[i]);
764
vector2[i] = c1*vector1[i] + c2*vector2[i];
765
//fprintf(stderr, "%e\n", vector2[i]);
766
}
767
768
return 1;
769
}
770
771
/*
772
* computes A = A*vector
773
*/
774
int SparseMatrix_mul_vector(SuperMatrix *A, double *vector) {
775
NCformat *Astore;
776
double *result;
777
int i, j, row_index;
778
int m, n;
779
double *a;
780
int *asub, *xa;
781
782
m = A->nrow;
783
n = A->ncol;
784
Astore = A->Store;
785
a = Astore->nzval;
786
asub = Astore->rowind;
787
xa = Astore->colptr;
788
789
if ( !(result = (double *) calloc(m, sizeof(double))) )
790
fatal("Malloc fails for result[].\n");
791
792
for(i=0; i<m; i++)
793
result[i] = 0;
794
795
for(i=0; i<n; i++){
796
j = xa[i];
797
while(j<xa[i+1]){
798
row_index = asub[j];
799
result[row_index] += a[j] * vector[i];
800
j++;
801
}
802
}
803
804
copy_dvector(vector, result, m);
805
806
free(result);
807
808
return 1;
809
}
810
811
void cooTocsv(char *filename, int size, int nnz, int *cooX, int *cooY, double *cooV) {
812
int i, j, k;
813
double **matrix;
814
815
matrix = calloc(size, sizeof(double *));
816
817
for(i = 0; i < size; i++)
818
matrix[i] = calloc(size, sizeof(double));
819
820
for(i = 0; i < nnz; i++) {
821
matrix[cooX[i]][cooY[i]] = cooV[i];
822
}
823
824
FILE *fp = fopen(filename, "w");
825
826
fprintf(fp, ",");
827
for(i = 0; i < size-1; i++)
828
fprintf(fp, "%d, ", i);
829
830
fprintf(fp, "%d\n", size-1);
831
832
for(i = 0; i < size; i++) {
833
fprintf(fp, "%d, ", i);
834
for(j = 0; j < size-1; j++) {
835
fprintf(fp, "%e, ", matrix[i][j]);
836
}
837
fprintf(fp, "%e\n", matrix[i][size-1]);
838
}
839
840
for(i = 0; i < size; i++)
841
free(matrix[i]);
842
843
free(matrix);
844
845
fclose(fp);
846
}
847
848
void diagTocsv(char *filename, diagonal_matrix_t *diag) {
849
int n = diag->n;
850
double *vals = diag->vals;
851
int i, j;
852
853
FILE *fp = fopen(filename, "w");
854
855
fprintf(fp, ",");
856
for(i = 0; i < n-1; i++)
857
fprintf(fp, "%d, ", i);
858
859
fprintf(fp, "%d\n", n-1);
860
861
for(i = 0; i < n; i++) {
862
fprintf(fp, "%d, ", i);
863
for(j = 0; j < n-1; j++) {
864
if(i != j)
865
fprintf(fp, "0, ");
866
else
867
fprintf(fp, "%e, ", vals[i]);
868
}
869
870
if(i == n-1)
871
fprintf(fp, "%e\n", vals[n-1]);
872
else
873
fprintf(fp, "0\n");
874
}
875
876
fclose(fp);
877
}
878
879
void vectorTocsv(char *filename, int size, double *vector) {
880
FILE *fp = fopen(filename, "w");
881
int i;
882
883
fprintf(fp, ",0\n");
884
for(i = 0; i < size; i++)
885
fprintf(fp, "%d, %e\n", i, vector[i]);
886
887
fclose(fp);
888
}
889
890
#endif
891
892