tranfi 0.1.2 → 0.2.1
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.
- package/LICENSE +177 -0
- package/NOTICE +8 -0
- package/README.md +443 -51
- package/app/assets/{index-pDFMluyz.js → index-BIAIKnrp.js} +1 -1
- package/app/index.html +1 -1
- package/binding.gyp +55 -3
- package/csrc/arena.c +7 -5
- package/csrc/batch.c +818 -71
- package/csrc/buffer.c +84 -8
- package/csrc/cJSON.c +262 -19
- package/csrc/cJSON.h +17 -1
- package/csrc/codec_csv.c +1074 -181
- package/csrc/codec_jsonl.c +830 -118
- package/csrc/codec_table.c +108 -78
- package/csrc/codec_text.c +286 -68
- package/csrc/compiler.c +31 -3
- package/csrc/config.h +21 -0
- package/csrc/dsl.c +4722 -485
- package/csrc/expr.c +363 -55
- package/csrc/expr.h +2 -0
- package/csrc/internal.h +316 -27
- package/csrc/ir.c +65 -18
- package/csrc/ir.h +41 -0
- package/csrc/ir_schema.c +20 -5
- package/csrc/ir_serialize.c +68 -6
- package/csrc/ir_sql.c +796 -185
- package/csrc/ir_validate.c +462 -6
- package/csrc/json_path.c +210 -0
- package/csrc/main.c +879 -30
- package/csrc/memory_estimate.c +477 -0
- package/csrc/op_acf.c +171 -21
- package/csrc/op_across.c +477 -0
- package/csrc/op_anomaly.c +167 -32
- package/csrc/op_assert.c +761 -0
- package/csrc/op_bin.c +168 -29
- package/csrc/op_cast.c +383 -55
- package/csrc/op_clip.c +30 -19
- package/csrc/op_date_trunc.c +208 -34
- package/csrc/op_datetime.c +259 -77
- package/csrc/op_derive.c +65 -97
- package/csrc/op_diff.c +146 -30
- package/csrc/op_ewma.c +149 -30
- package/csrc/op_explode.c +124 -26
- package/csrc/op_fill_down.c +125 -53
- package/csrc/op_fill_null.c +176 -31
- package/csrc/op_filter.c +89 -40
- package/csrc/op_frequency.c +571 -43
- package/csrc/op_grep.c +36 -18
- package/csrc/op_group_agg.c +1790 -119
- package/csrc/op_hash.c +48 -15
- package/csrc/op_head.c +21 -86
- package/csrc/op_interpolate.c +268 -62
- package/csrc/op_join.c +2700 -182
- package/csrc/op_json_extract.c +227 -0
- package/csrc/op_json_filter.c +384 -0
- package/csrc/op_json_flatten.c +293 -0
- package/csrc/op_json_schema.c +503 -0
- package/csrc/op_label_encode.c +328 -53
- package/csrc/op_lag.c +181 -0
- package/csrc/op_lead.c +141 -89
- package/csrc/op_normalize.c +363 -79
- package/csrc/op_onehot.c +345 -73
- package/csrc/op_pivot.c +1546 -162
- package/csrc/op_quarantine.c +189 -0
- package/csrc/op_registry.c +2062 -166
- package/csrc/op_rename.c +41 -50
- package/csrc/op_replace.c +270 -118
- package/csrc/op_rleid.c +297 -0
- package/csrc/op_rowid.c +559 -0
- package/csrc/op_sample.c +80 -23
- package/csrc/op_schema.c +1341 -0
- package/csrc/op_schema_infer.c +252 -0
- package/csrc/op_select.c +265 -65
- package/csrc/op_set.c +3449 -0
- package/csrc/op_skip.c +30 -87
- package/csrc/op_sort.c +670 -124
- package/csrc/op_source_name.c +120 -0
- package/csrc/op_split.c +65 -28
- package/csrc/op_split_data.c +41 -9
- package/csrc/op_stack.c +178 -222
- package/csrc/op_stats.c +206 -110
- package/csrc/op_step.c +217 -55
- package/csrc/op_tail.c +21 -12
- package/csrc/op_tee.c +338 -0
- package/csrc/op_top.c +260 -53
- package/csrc/op_trim.c +48 -19
- package/csrc/op_unique.c +1193 -150
- package/csrc/op_unpivot.c +100 -66
- package/csrc/op_validate.c +601 -24
- package/csrc/op_window.c +492 -51
- package/csrc/path_policy.c +85 -0
- package/csrc/pipeline.c +872 -99
- package/csrc/recipes.c +3 -1
- package/csrc/report.c +73 -30
- package/csrc/selector.c +1097 -0
- package/csrc/size_utils.c +352 -0
- package/csrc/spill.c +317 -0
- package/csrc/spill.h +21 -0
- package/csrc/tranfi.h +169 -1
- package/csrc/transform.h +209 -0
- package/csrc/transform_api.c +2237 -0
- package/csrc/transform_categorical.c +923 -0
- package/csrc/transform_internal.h +472 -0
- package/csrc/transform_json.c +3812 -0
- package/csrc/transform_numeric.c +1966 -0
- package/csrc/transform_sha256.c +154 -0
- package/csrc/transform_wasm.h +162 -0
- package/csrc/transform_wasm_api.c +1373 -0
- package/csrc/wasm_api.c +70 -9
- package/napi_api.c +219 -11
- package/napi_transform.c +1648 -0
- package/napi_transform.h +8 -0
- package/package.json +27 -11
- package/scripts/install-native.js +76 -0
- package/scripts/prepack.js +64 -0
- package/scripts/sync-csrc.js +23 -0
- package/src/cli.js +81 -41
- package/src/engines/duckdb.js +45 -12
- package/src/index.js +661 -42
- package/src/memory_policy.js +411 -0
- package/src/native.js +1 -5
- package/src/pipeline.js +454 -31
- package/src/recipe_json.js +80 -0
- package/src/server.js +10 -8
- package/src/transform.js +403 -0
- package/src/transform_error.js +10 -0
- package/src/wasm.js +6 -4
- package/wasm/index.js +498 -10
- package/wasm/tranfi_core.js +0 -0
- package/wasm/transform.js +1156 -0
- package/wasm/worker.js +786 -0
- package/csrc/plan.c +0 -206
package/csrc/op_sample.c
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* op_sample.c
|
|
2
|
+
* op_sample.c -- Reservoir sampling (Algorithm R). Bounded memory.
|
|
3
3
|
*
|
|
4
|
-
* Config: {"n": 100}
|
|
4
|
+
* Config: {"n": 100, "seed": 123} or {"n": 100, "seed": "random"}
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
#include "internal.h"
|
|
8
8
|
#include "cJSON.h"
|
|
9
|
+
#include <stdint.h>
|
|
9
10
|
#include <stdlib.h>
|
|
10
11
|
#include <string.h>
|
|
11
12
|
#include <time.h>
|
|
@@ -15,9 +16,33 @@ typedef struct {
|
|
|
15
16
|
tf_batch *buf;
|
|
16
17
|
size_t seen; /* total rows seen */
|
|
17
18
|
int has_schema;
|
|
18
|
-
|
|
19
|
+
uint64_t rng;
|
|
19
20
|
} sample_state;
|
|
20
21
|
|
|
22
|
+
static uint64_t sample_random_seed(void) {
|
|
23
|
+
uintptr_t stack_marker = 0;
|
|
24
|
+
uintptr_t stack_addr = (uintptr_t)&stack_marker;
|
|
25
|
+
return ((uint64_t)time(NULL) << 32) ^ (uint64_t)clock() ^ (uint64_t)stack_addr;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static uint64_t sample_next_u64(sample_state *st) {
|
|
29
|
+
st->rng += UINT64_C(0x9E3779B97F4A7C15);
|
|
30
|
+
uint64_t z = st->rng;
|
|
31
|
+
z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);
|
|
32
|
+
z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
|
|
33
|
+
return z ^ (z >> 31);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static size_t sample_bounded(sample_state *st, size_t bound) {
|
|
37
|
+
if (bound <= 1) return 0;
|
|
38
|
+
uint64_t b = (uint64_t)bound;
|
|
39
|
+
uint64_t threshold = (uint64_t)(-b) % b;
|
|
40
|
+
for (;;) {
|
|
41
|
+
uint64_t r = sample_next_u64(st);
|
|
42
|
+
if (r >= threshold) return (size_t)(r % b);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
21
46
|
static int sample_process(tf_step *self, tf_batch *in, tf_batch **out,
|
|
22
47
|
tf_side_channels *side) {
|
|
23
48
|
(void)side;
|
|
@@ -27,22 +52,22 @@ static int sample_process(tf_step *self, tf_batch *in, tf_batch **out,
|
|
|
27
52
|
if (!st->has_schema) {
|
|
28
53
|
st->buf = tf_batch_create(in->n_cols, st->n);
|
|
29
54
|
if (!st->buf) return TF_ERROR;
|
|
30
|
-
|
|
31
|
-
tf_batch_set_schema(st->buf, c, in->col_names[c], in->col_types[c]);
|
|
55
|
+
if (tf_batch_clone_schema(st->buf, in) != TF_OK) return TF_ERROR;
|
|
32
56
|
st->has_schema = 1;
|
|
33
57
|
}
|
|
34
58
|
|
|
35
59
|
for (size_t r = 0; r < in->n_rows; r++) {
|
|
60
|
+
if (st->seen == SIZE_MAX) {
|
|
61
|
+
tf_set_last_error("sample: row count overflow");
|
|
62
|
+
return TF_ERROR;
|
|
63
|
+
}
|
|
36
64
|
if (st->seen < st->n) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
st->buf->n_rows = st->seen + 1;
|
|
65
|
+
if (tf_batch_copy_row(st->buf, st->seen, in, r) != TF_OK) return TF_ERROR;
|
|
66
|
+
if (tf_batch_expose_row(st->buf, st->seen) != TF_OK) return TF_ERROR;
|
|
40
67
|
} else {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
tf_batch_copy_row(st->buf, j, in, r);
|
|
45
|
-
}
|
|
68
|
+
size_t j = sample_bounded(st, st->seen + 1);
|
|
69
|
+
if (j < st->n && tf_batch_copy_row(st->buf, j, in, r) != TF_OK)
|
|
70
|
+
return TF_ERROR;
|
|
46
71
|
}
|
|
47
72
|
st->seen++;
|
|
48
73
|
}
|
|
@@ -57,15 +82,22 @@ static int sample_flush(tf_step *self, tf_batch **out, tf_side_channels *side) {
|
|
|
57
82
|
|
|
58
83
|
if (!st->buf || st->buf->n_rows == 0) return TF_OK;
|
|
59
84
|
|
|
60
|
-
/* Copy buffer to output */
|
|
61
85
|
size_t n = st->buf->n_rows;
|
|
62
86
|
tf_batch *ob = tf_batch_create(st->buf->n_cols, n);
|
|
63
87
|
if (!ob) return TF_ERROR;
|
|
64
|
-
|
|
65
|
-
|
|
88
|
+
if (tf_batch_clone_schema(ob, st->buf) != TF_OK) {
|
|
89
|
+
tf_batch_free(ob);
|
|
90
|
+
return TF_ERROR;
|
|
91
|
+
}
|
|
66
92
|
for (size_t i = 0; i < n; i++) {
|
|
67
|
-
tf_batch_copy_row(ob, i, st->buf, i)
|
|
68
|
-
|
|
93
|
+
if (tf_batch_copy_row(ob, i, st->buf, i) != TF_OK) {
|
|
94
|
+
tf_batch_free(ob);
|
|
95
|
+
return TF_ERROR;
|
|
96
|
+
}
|
|
97
|
+
if (tf_batch_expose_row(ob, i) != TF_OK) {
|
|
98
|
+
tf_batch_free(ob);
|
|
99
|
+
return TF_ERROR;
|
|
100
|
+
}
|
|
69
101
|
}
|
|
70
102
|
|
|
71
103
|
*out = ob;
|
|
@@ -83,15 +115,40 @@ static void sample_destroy(tf_step *self) {
|
|
|
83
115
|
|
|
84
116
|
tf_step *tf_sample_create(const cJSON *args) {
|
|
85
117
|
if (!args) return NULL;
|
|
86
|
-
|
|
87
|
-
|
|
118
|
+
size_t n = 0;
|
|
119
|
+
int has_n = tf_json_get_size_arg(args, "n", 1, TF_MAX_OUTPUT_ROWS_PER_BATCH, &n, "sample");
|
|
120
|
+
if (has_n <= 0) return NULL;
|
|
88
121
|
|
|
89
122
|
sample_state *st = calloc(1, sizeof(sample_state));
|
|
90
123
|
if (!st) return NULL;
|
|
91
|
-
st->n =
|
|
92
|
-
st->
|
|
124
|
+
st->n = n;
|
|
125
|
+
st->rng = 0;
|
|
126
|
+
|
|
127
|
+
cJSON *seed_json = cJSON_GetObjectItemCaseSensitive(args, "seed");
|
|
128
|
+
if (seed_json) {
|
|
129
|
+
if (cJSON_IsString(seed_json)) {
|
|
130
|
+
if (strcmp(seed_json->valuestring, "random") != 0) {
|
|
131
|
+
tf_set_last_error("sample: seed must be an integer or 'random'");
|
|
132
|
+
free(st);
|
|
133
|
+
return NULL;
|
|
134
|
+
}
|
|
135
|
+
st->rng = sample_random_seed();
|
|
136
|
+
} else if (cJSON_IsNumber(seed_json) && seed_json->valuedouble >= 0.0) {
|
|
137
|
+
size_t parsed = 0;
|
|
138
|
+
if (tf_json_size_value(seed_json, "seed", 0, TF_MAX_SAFE_SIZE_ARG,
|
|
139
|
+
&parsed, "sample") < 0) {
|
|
140
|
+
free(st);
|
|
141
|
+
return NULL;
|
|
142
|
+
}
|
|
143
|
+
st->rng = (uint64_t)parsed;
|
|
144
|
+
} else {
|
|
145
|
+
tf_set_last_error("sample: seed must be an integer or 'random'");
|
|
146
|
+
free(st);
|
|
147
|
+
return NULL;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
93
150
|
|
|
94
|
-
tf_step *step =
|
|
151
|
+
tf_step *step = calloc(1, sizeof(tf_step));
|
|
95
152
|
if (!step) { free(st); return NULL; }
|
|
96
153
|
step->process = sample_process;
|
|
97
154
|
step->flush = sample_flush;
|