Merge pull request #113 from gitter-badger/gitter-badge
[sddekit.git] / src / out_mem.c
blob4910745188bb1ef52c0fa8eea80972defc503c1b
1 /* copyright 2016 Apache 2 sddekit authors */
3 #include "sddekit.h"
5 /* auto-allocating array */
6 typedef struct mem_data {
7 sd_out out_if;
8 sd_out_mem mem_if;
9 uint32_t n_sample, capacity, nx, nc;
10 double *xs, *cs;
11 } mem_data;
13 static uint32_t
14 mem_get_n_sample(sd_out_mem *out)
16 return ((mem_data*) out->ptr)->n_sample;
19 static uint32_t
20 mem_get_nx(sd_out_mem *out)
22 return ((mem_data*) out->ptr)->nx;
25 static uint32_t
26 mem_get_nc(sd_out_mem *out)
28 return ((mem_data*) out->ptr)->nc;
31 static double *
32 mem_get_xs(sd_out_mem *out)
34 return ((mem_data*) out->ptr)->xs;
37 static double *
38 mem_get_cs(sd_out_mem *out)
40 return ((mem_data*) out->ptr)->cs;
43 static sd_out *
44 mem_get_out(sd_out_mem *out)
46 return &(((mem_data*)out->ptr)->out_if);
49 static uint32_t
50 mem_get_capacity(sd_out_mem *out)
52 return ((mem_data*)out->ptr)->capacity;
55 static void
56 mem_free(sd_out *out)
58 mem_data *d = out->ptr;
59 if (d->xs!=NULL)
60 sd_free(d->xs);
61 if (d->cs!=NULL)
62 sd_free(d->cs);
63 sd_free(d);
66 static sd_stat
67 mem_apply(sd_out *out, double t,
68 uint32_t nx, double * restrict x,
69 uint32_t nc, double * restrict c)
71 mem_data *d = out->ptr;
72 (void) t;
73 if (d->capacity==0) {
74 int err;
75 /* first alloc */
76 d->nx = nx;
77 d->nc = nc;
78 err = (d->xs = sd_malloc (sizeof(double)*nx))==NULL;
79 err |= (d->cs = sd_malloc (sizeof(double)*nc))==NULL;
80 if (err) {
81 sd_err("failed to allocate memory.");
82 if (d->xs!=NULL) sd_free(d->xs);
83 if (d->cs!=NULL) sd_free(d->cs);
84 return SD_ERR;
86 d->capacity = 1;
88 memcpy(d->xs + d->n_sample*nx, x, sizeof(double)*nx);
89 memcpy(d->cs + d->n_sample*nc, c, sizeof(double)*nc);
90 d->n_sample++;
91 if (d->n_sample==d->capacity) {
92 double *x_, *c_;
93 /* expand buffer */
94 x_ = sd_realloc (d->xs, sizeof(double)*nx*2*d->capacity);
95 if (x_==NULL) {
96 sd_err("failed to allocate memory.");
97 return SD_ERR;
98 } else {
99 /* save new ptr in case c_ realloc fails, free can still
100 * handle x_
102 d->xs = x_;
104 c_ = sd_realloc (d->cs, sizeof(double)*nc*2*d->capacity);
105 if (c_==NULL) {
106 sd_err("failed to allocate memory.");
107 return SD_ERR;
109 d->capacity *= 2;
110 d->xs = x_;
111 d->cs = c_;
113 return SD_CONT;
116 static sd_out_mem
117 mem_defaults = { .out = &mem_get_out, .get_nx=&mem_get_nx, .get_nc=&mem_get_nc,
118 .get_n_sample=&mem_get_n_sample, .get_capacity=&mem_get_capacity,
119 .get_xs=&mem_get_xs, .get_cs=&mem_get_cs
122 static sd_out
123 mem_out_defaults = { .free = &mem_free,.apply = &mem_apply };
125 sd_out_mem *
126 sd_out_mem_new()
128 mem_data *d = NULL;
129 if ((d = sd_malloc(sizeof(mem_data))) == NULL)
131 sd_err("alloc failed for new mem output.");
132 return NULL;
134 d->xs = NULL;
135 d->cs = NULL;
136 d->n_sample = 0;
137 d->capacity = 0;
138 d->mem_if = mem_defaults;
139 d->out_if = mem_out_defaults;
140 d->out_if.ptr = d->mem_if.ptr = d;
141 return &(d->mem_if);