Skip to content

Commit 808a85b

Browse files
committed
fix(eval): align division semantics
Closes #186
1 parent 371eb98 commit 808a85b

23 files changed

Lines changed: 1463 additions & 1497 deletions

src/lang/eval.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ ray_t* atomic_map_binary_op(ray_binary_fn fn, uint16_t dag_opcode, ray_t* left,
496496

497497
/* DAG executor — for F64 and comparisons */
498498
if (!force_boxed && dag_opcode > 0) {
499-
int is_idiv = (dag_opcode == OP_DIV || dag_opcode == OP_MOD);
499+
int is_idiv = (dag_opcode == OP_MOD);
500500
int is_cmp = (dag_opcode >= OP_EQ && dag_opcode <= OP_GE);
501501

502502
/* Classify operands: numeric/temporal vectors or scalars */
@@ -561,8 +561,6 @@ ray_t* atomic_map_binary_op(ray_binary_fn fn, uint16_t dag_opcode, ray_t* left,
561561
if (lop && rop) {
562562
ray_op_t* root = ray_binop(g, dag_opcode, lop, rop);
563563
if (root) {
564-
/* For integer floor-division: ray_binop sets F64 output
565-
* for OP_DIV; override to I64 for floor-div with null prop */
566564
if (is_idiv) root->out_type = RAY_I64;
567565
ray_t* result = ray_execute(g, root);
568566
ray_graph_free(g);
@@ -571,13 +569,6 @@ ray_t* atomic_map_binary_op(ray_binary_fn fn, uint16_t dag_opcode, ray_t* left,
571569
if (ray_is_vec(result) && result->type != out_type &&
572570
ray_elem_size(result->type) == ray_elem_size(out_type))
573571
result->type = out_type;
574-
/* Floor-div post-pass (OP_DIV only) */
575-
if (dag_opcode == OP_DIV && ray_is_vec(result) &&
576-
result->type == RAY_F64) {
577-
double* d = (double*)ray_data(result);
578-
for (int64_t fi = 0; fi < result->len; fi++)
579-
d[fi] = floor(d[fi]);
580-
}
581572
ray_release(e0);
582573
return result;
583574
}
@@ -2029,7 +2020,7 @@ vm_error_cleanup: {
20292020

20302021

20312022
/* ray_enlist_fn, ray_dict_fn, ray_nil_fn, ray_where_fn, ray_group_fn,
2032-
* ray_concat_fn, ray_raze_fn, ray_within_fn, ray_fdiv_fn
2023+
* ray_concat_fn, ray_raze_fn, ray_within_fn
20332024
* moved to ops/builtins.c */
20342025

20352026
/* ══════════════════════════════════════════
@@ -2314,7 +2305,7 @@ static void ray_register_builtins(void) {
23142305
register_binary("concat", RAY_FN_NONE, ray_concat_fn);
23152306
register_unary("raze", RAY_FN_NONE, ray_raze_fn);
23162307
register_binary("within", RAY_FN_NONE, ray_within_fn);
2317-
register_binary("div", RAY_FN_ATOMIC, ray_fdiv_fn);
2308+
register_binary("div", RAY_FN_ATOMIC, ray_idiv_fn);
23182309
register_binary("rand", RAY_FN_NONE, ray_rand_fn);
23192310
register_binary("bin", RAY_FN_NONE, ray_bin_fn);
23202311
register_binary("binr", RAY_FN_NONE, ray_binr_fn);

src/lang/eval.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ ray_t* ray_add_fn(ray_t* a, ray_t* b);
192192
ray_t* ray_sub_fn(ray_t* a, ray_t* b);
193193
ray_t* ray_mul_fn(ray_t* a, ray_t* b);
194194
ray_t* ray_div_fn(ray_t* a, ray_t* b);
195+
ray_t* ray_idiv_fn(ray_t* a, ray_t* b);
195196
ray_t* ray_mod_fn(ray_t* a, ray_t* b);
196197

197198
/* Comparison */

src/lang/internal.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,6 @@ ray_t* ray_nil_fn(ray_t* x);
492492
ray_t* ray_where_fn(ray_t* x);
493493
ray_t* ray_raze_fn(ray_t* x);
494494
ray_t* ray_within_fn(ray_t* vals, ray_t* range);
495-
ray_t* ray_fdiv_fn(ray_t* a, ray_t* b);
496495

497496
/* Query bridge builtins (formerly in eval.c, now in ops/query.c) */
498497
ray_t* ray_select_fn(ray_t** args, int64_t n);

src/ops/arith.c

Lines changed: 18 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -186,70 +186,30 @@ ray_t* ray_mul_fn(ray_t* a, ray_t* b) {
186186
}
187187

188188
ray_t* ray_div_fn(ray_t* a, ray_t* b) {
189-
/* Temporal / numeric → temporal (same type as left operand) */
190-
if (is_temporal(a) && is_numeric(b)) {
191-
if (RAY_ATOM_IS_NULL(b) || RAY_ATOM_IS_NULL(a))
192-
return ray_typed_null(a->type);
193-
if (is_float_op(a, b)) {
194-
double bv = as_f64(b);
195-
if (bv == 0.0)
196-
return ray_typed_null(a->type);
197-
int64_t result = (int64_t)floor((double)a->i64 / bv);
198-
if (a->type == -RAY_TIME) return ray_time(result);
199-
if (a->type == -RAY_DATE) return ray_date(result);
200-
return ray_timestamp(result);
201-
}
202-
int64_t bv = as_i64(b);
203-
if (bv == 0)
204-
return ray_typed_null(a->type);
205-
int64_t av = a->i64;
206-
int64_t q = av / bv;
207-
if ((av ^ bv) < 0 && q * bv != av) q--;
208-
if (a->type == -RAY_TIME) return ray_time(q);
209-
if (a->type == -RAY_DATE) return ray_date(q);
210-
return ray_timestamp(q);
211-
}
212189
if (!is_numeric(a) || !is_numeric(b))
213190
return ray_error("type", "cannot divide %s by %s",
214191
ray_type_name(a->type), ray_type_name(b->type));
215-
/* u8: unsigned byte division — div by 0 returns 0 */
216-
if (a->type == -RAY_U8) {
217-
uint8_t bv = (uint8_t)as_i64(b);
218-
if (bv == 0 || RAY_ATOM_IS_NULL(b)) return make_u8(0);
219-
if (RAY_ATOM_IS_NULL(a)) return make_u8(0);
220-
return make_u8((uint8_t)((uint8_t)as_i64(a) / bv));
221-
}
222-
/* Null propagation — null operand → typed null matching left operand type */
223192
if (RAY_ATOM_IS_NULL(a) || RAY_ATOM_IS_NULL(b))
224-
return ray_typed_null(a->type);
193+
return ray_typed_null(-RAY_F64);
194+
double bv = as_f64(b);
195+
if (bv == 0.0)
196+
return ray_typed_null(-RAY_F64);
197+
return make_f64(as_f64(a) / bv);
198+
}
225199

226-
/* Integer (floor) division — always returns integer.
227-
* Float operands are converted to i64 via floor(a/b). */
228-
if (is_float_op(a, b)) {
229-
double bv = as_f64(b);
230-
if (bv == 0.0)
231-
return ray_typed_null(a->type);
232-
double result = floor(as_f64(a) / bv);
233-
/* Return type matches LEFT operand */
234-
if (a->type == -RAY_F64) return make_f64(result);
235-
if (a->type == -RAY_I16) return make_i16((int16_t)(int64_t)result);
236-
if (a->type == -RAY_I32) return make_i32((int32_t)(int64_t)result);
237-
if (result >= (double)INT64_MIN && result <= (double)INT64_MAX)
238-
return make_i64((int64_t)result);
200+
ray_t* ray_idiv_fn(ray_t* a, ray_t* b) {
201+
if (!is_numeric(a) || !is_numeric(b))
202+
return ray_error("type", "cannot div %s by %s",
203+
ray_type_name(a->type), ray_type_name(b->type));
204+
if (RAY_ATOM_IS_NULL(a) || RAY_ATOM_IS_NULL(b))
239205
return ray_typed_null(-RAY_I64);
240-
}
241-
int64_t bv = as_i64(b);
242-
if (bv == 0)
243-
return ray_typed_null(a->type);
244-
245-
int64_t av = as_i64(a);
246-
/* Floor division (toward -inf) */
247-
int64_t q = av / bv;
248-
if ((av ^ bv) < 0 && q * bv != av) q--;
249-
/* Return type matches LEFT operand for i16/i32 */
250-
if (a->type == -RAY_I16) return make_i16((int16_t)q);
251-
if (a->type == -RAY_I32) return make_i32((int32_t)q);
252-
return make_i64(q);
206+
double bv = as_f64(b);
207+
if (bv == 0.0)
208+
return ray_typed_null(-RAY_I64);
209+
double q = floor(as_f64(a) / bv);
210+
if (q < (double)INT64_MIN || q > (double)INT64_MAX)
211+
return ray_typed_null(-RAY_I64);
212+
return make_i64((int64_t)q);
253213
}
254214

255215
ray_t* ray_mod_fn(ray_t* a, ray_t* b) {

src/ops/builtins.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2668,14 +2668,3 @@ ray_t* ray_within_fn(ray_t* vals, ray_t* range) {
26682668
result->len = n;
26692669
return result;
26702670
}
2671-
2672-
/* (div a b) -> float division (always returns f64) */
2673-
ray_t* ray_fdiv_fn(ray_t* a, ray_t* b) {
2674-
if (!ray_is_atom(a) || !ray_is_atom(b)) return ray_error("type", NULL);
2675-
if (!is_numeric(a) || !is_numeric(b)) return ray_error("type", NULL);
2676-
/* Null propagation */
2677-
if (RAY_ATOM_IS_NULL(a) || RAY_ATOM_IS_NULL(b)) return ray_typed_null(-RAY_F64);
2678-
double fa = as_f64(a), fb = as_f64(b);
2679-
if (fb == 0.0) return ray_typed_null(-RAY_F64);
2680-
return make_f64(fa / fb);
2681-
}

src/ops/dump.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const char* ray_opcode_name(uint16_t op) {
5151
case OP_SUB: return "SUB";
5252
case OP_MUL: return "MUL";
5353
case OP_DIV: return "DIV";
54+
case OP_IDIV: return "IDIV";
5455
case OP_MOD: return "MOD";
5556
case OP_EQ: return "EQ";
5657
case OP_NE: return "NE";

src/ops/exec.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -974,7 +974,7 @@ static ray_t* exec_node_inner(ray_graph_t* g, ray_op_t* op) {
974974
case OP_LOG: case OP_EXP: case OP_CEIL: case OP_FLOOR: case OP_ROUND:
975975
case OP_ISNULL: case OP_CAST:
976976
/* Binary element-wise */
977-
case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_MOD:
977+
case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: case OP_MOD:
978978
case OP_EQ: case OP_NE: case OP_LT: case OP_LE:
979979
case OP_GT: case OP_GE: case OP_AND: case OP_OR:
980980
case OP_MIN2: case OP_MAX2: {
@@ -2010,7 +2010,7 @@ static bool op_streamable(uint16_t opc) {
20102010
case OP_LOG: case OP_EXP: case OP_CEIL: case OP_FLOOR: case OP_ROUND:
20112011
case OP_ISNULL: case OP_CAST:
20122012
/* Element-wise binary */
2013-
case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_MOD:
2013+
case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: case OP_MOD:
20142014
case OP_EQ: case OP_NE: case OP_LT: case OP_LE:
20152015
case OP_GT: case OP_GE: case OP_AND: case OP_OR:
20162016
case OP_MIN2: case OP_MAX2: case OP_IF: case OP_IN: case OP_NOT_IN:

src/ops/expr.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ static bool eval_const_numeric_expr(ray_graph_t* g, ray_op_t* op,
9898
}
9999

100100
if (op->arity != 2 || !op->inputs[0] || !op->inputs[1]) return false;
101-
if (op->opcode < OP_ADD || op->opcode > OP_MAX2) return false;
101+
if ((op->opcode < OP_ADD || op->opcode > OP_MAX2) && op->opcode != OP_IDIV) return false;
102102

103103
double lf = 0.0, rf = 0.0;
104104
int64_t li = 0, ri = 0;
@@ -115,6 +115,7 @@ static bool eval_const_numeric_expr(ray_graph_t* g, ray_op_t* op,
115115
case OP_SUB: r = lv - rv; break;
116116
case OP_MUL: r = lv * rv; break;
117117
case OP_DIV: r = rv != 0.0 ? lv / rv : NAN; break;
118+
case OP_IDIV: r = rv != 0.0 ? floor(lv / rv) : NAN; break;
118119
case OP_MOD: { if (rv != 0.0) { r = fmod(lv, rv); if (r && ((r > 0) != (rv > 0))) r += rv; } else { r = NAN; } } break;
119120
case OP_MIN2: r = lv < rv ? lv : rv; break;
120121
case OP_MAX2: r = lv > rv ? lv : rv; break;
@@ -135,6 +136,10 @@ static bool eval_const_numeric_expr(ray_graph_t* g, ray_op_t* op,
135136
if (ri==0) return false;
136137
r = li/ri; if ((li^ri)<0 && r*ri!=li) r--;
137138
break;
139+
case OP_IDIV:
140+
if (ri==0) return false;
141+
r = li/ri; if ((li^ri)<0 && r*ri!=li) r--;
142+
break;
138143
case OP_MOD:
139144
if (ri==0) return false;
140145
r = li%ri; if (r && (r^ri)<0) r+=ri;
@@ -1538,6 +1543,7 @@ static void binary_range(ray_op_t* op, int8_t out_type,
15381543
case OP_SUB: for (int64_t i=0;i<n;i++) { double lv=LV_READ(i),rv=RV_READ(i); odst[i]=lv-rv; } break;
15391544
case OP_MUL: for (int64_t i=0;i<n;i++) { double lv=LV_READ(i),rv=RV_READ(i); odst[i]=lv*rv; } break;
15401545
case OP_DIV: for (int64_t i=0;i<n;i++) { double lv=LV_READ(i),rv=RV_READ(i); odst[i]=rv!=0.0?lv/rv:NAN; } break;
1546+
case OP_IDIV: for (int64_t i=0;i<n;i++) { double lv=LV_READ(i),rv=RV_READ(i); odst[i]=rv!=0.0?floor(lv/rv):NAN; } break;
15411547
case OP_MOD: for (int64_t i=0;i<n;i++) { double lv=LV_READ(i),rv=RV_READ(i); double r; if(rv!=0.0){r=fmod(lv,rv);if(r&&((r>0)!=(rv>0)))r+=rv;}else r=NAN; odst[i]=r; } break;
15421548
case OP_MIN2: for (int64_t i=0;i<n;i++) { double lv=LV_READ(i),rv=RV_READ(i); odst[i]=lv<rv?lv:rv; } break;
15431549
case OP_MAX2: for (int64_t i=0;i<n;i++) { double lv=LV_READ(i),rv=RV_READ(i); odst[i]=lv>rv?lv:rv; } break;
@@ -1550,6 +1556,7 @@ static void binary_range(ray_op_t* op, int8_t out_type,
15501556
case OP_SUB: for(int64_t i=0;i<n;i++){int64_t li=(int64_t)LV_READ(i),ri=(int64_t)RV_READ(i);odst[i]=(int64_t)((uint64_t)li-(uint64_t)ri);}break;
15511557
case OP_MUL: for(int64_t i=0;i<n;i++){int64_t li=(int64_t)LV_READ(i),ri=(int64_t)RV_READ(i);odst[i]=(int64_t)((uint64_t)li*(uint64_t)ri);}break;
15521558
case OP_DIV: for(int64_t i=0;i<n;i++){int64_t li=(int64_t)LV_READ(i),ri=(int64_t)RV_READ(i);int64_t r;if(ri==0||(ri==-1&&li==((int64_t)1<<63))){r=0;}else{r=li/ri;if((li^ri)<0&&r*ri!=li)r--;}odst[i]=r;}break;
1559+
case OP_IDIV:for(int64_t i=0;i<n;i++){double lv=LV_READ(i),rv=RV_READ(i);odst[i]=rv!=0.0?(int64_t)floor(lv/rv):0;}break;
15531560
case OP_MOD: for(int64_t i=0;i<n;i++){int64_t li=(int64_t)LV_READ(i),ri=(int64_t)RV_READ(i);int64_t r;if(ri==0||(ri==-1&&li==((int64_t)1<<63))){r=0;}else{r=li%ri;if(r&&(r^ri)<0)r+=ri;}odst[i]=r;}break;
15541561
case OP_MIN2:for(int64_t i=0;i<n;i++){int64_t li=(int64_t)LV_READ(i),ri=(int64_t)RV_READ(i);odst[i]=li<ri?li:ri;}break;
15551562
case OP_MAX2:for(int64_t i=0;i<n;i++){int64_t li=(int64_t)LV_READ(i),ri=(int64_t)RV_READ(i);odst[i]=li>ri?li:ri;}break;
@@ -1562,6 +1569,7 @@ static void binary_range(ray_op_t* op, int8_t out_type,
15621569
case OP_SUB: for(int64_t i=0;i<n;i++){int32_t li=(int32_t)LV_READ(i),ri=(int32_t)RV_READ(i);odst[i]=(int32_t)((uint32_t)li-(uint32_t)ri);}break;
15631570
case OP_MUL: for(int64_t i=0;i<n;i++){int32_t li=(int32_t)LV_READ(i),ri=(int32_t)RV_READ(i);odst[i]=(int32_t)((uint32_t)li*(uint32_t)ri);}break;
15641571
case OP_DIV: for(int64_t i=0;i<n;i++){int32_t li=(int32_t)LV_READ(i),ri=(int32_t)RV_READ(i);int32_t r;if(ri==0||(ri==-1&&li==((int32_t)1<<31))){r=0;}else{r=li/ri;if((li^ri)<0&&r*ri!=li)r--;}odst[i]=r;}break;
1572+
case OP_IDIV:for(int64_t i=0;i<n;i++){double lv=LV_READ(i),rv=RV_READ(i);odst[i]=rv!=0.0?(int32_t)floor(lv/rv):0;}break;
15651573
case OP_MOD: for(int64_t i=0;i<n;i++){int32_t li=(int32_t)LV_READ(i),ri=(int32_t)RV_READ(i);int32_t r;if(ri==0||(ri==-1&&li==((int32_t)1<<31))){r=0;}else{r=li%ri;if(r&&(r^ri)<0)r+=ri;}odst[i]=r;}break;
15661574
case OP_MIN2:for(int64_t i=0;i<n;i++){int32_t li=(int32_t)LV_READ(i),ri=(int32_t)RV_READ(i);odst[i]=li<ri?li:ri;}break;
15671575
case OP_MAX2:for(int64_t i=0;i<n;i++){int32_t li=(int32_t)LV_READ(i),ri=(int32_t)RV_READ(i);odst[i]=li>ri?li:ri;}break;
@@ -1574,6 +1582,7 @@ static void binary_range(ray_op_t* op, int8_t out_type,
15741582
case OP_SUB: for(int64_t i=0;i<n;i++){int16_t li=(int16_t)LV_READ(i),ri=(int16_t)RV_READ(i);odst[i]=(int16_t)((uint16_t)li-(uint16_t)ri);}break;
15751583
case OP_MUL: for(int64_t i=0;i<n;i++){int16_t li=(int16_t)LV_READ(i),ri=(int16_t)RV_READ(i);odst[i]=(int16_t)((uint16_t)li*(uint16_t)ri);}break;
15761584
case OP_DIV: for(int64_t i=0;i<n;i++){int16_t li=(int16_t)LV_READ(i),ri=(int16_t)RV_READ(i);odst[i]=ri?li/ri:0;}break;
1585+
case OP_IDIV:for(int64_t i=0;i<n;i++){double lv=LV_READ(i),rv=RV_READ(i);odst[i]=rv!=0.0?(int16_t)floor(lv/rv):0;}break;
15771586
case OP_MOD: for(int64_t i=0;i<n;i++){int16_t li=(int16_t)LV_READ(i),ri=(int16_t)RV_READ(i);odst[i]=ri?li%ri:0;}break;
15781587
case OP_MIN2:for(int64_t i=0;i<n;i++){int16_t li=(int16_t)LV_READ(i),ri=(int16_t)RV_READ(i);odst[i]=li<ri?li:ri;}break;
15791588
case OP_MAX2:for(int64_t i=0;i<n;i++){int16_t li=(int16_t)LV_READ(i),ri=(int16_t)RV_READ(i);odst[i]=li>ri?li:ri;}break;
@@ -1586,6 +1595,7 @@ static void binary_range(ray_op_t* op, int8_t out_type,
15861595
case OP_SUB: for(int64_t i=0;i<n;i++){uint8_t li=(uint8_t)LV_READ(i),ri=(uint8_t)RV_READ(i);odst[i]=li-ri;}break;
15871596
case OP_MUL: for(int64_t i=0;i<n;i++){uint8_t li=(uint8_t)LV_READ(i),ri=(uint8_t)RV_READ(i);odst[i]=li*ri;}break;
15881597
case OP_DIV: for(int64_t i=0;i<n;i++){uint8_t li=(uint8_t)LV_READ(i),ri=(uint8_t)RV_READ(i);odst[i]=ri?li/ri:0;}break;
1598+
case OP_IDIV:for(int64_t i=0;i<n;i++){double lv=LV_READ(i),rv=RV_READ(i);odst[i]=rv!=0.0?(uint8_t)floor(lv/rv):0;}break;
15891599
case OP_MOD: for(int64_t i=0;i<n;i++){uint8_t li=(uint8_t)LV_READ(i),ri=(uint8_t)RV_READ(i);odst[i]=ri?li%ri:0;}break;
15901600
case OP_MIN2:for(int64_t i=0;i<n;i++){uint8_t li=(uint8_t)LV_READ(i),ri=(uint8_t)RV_READ(i);odst[i]=li<ri?li:ri;}break;
15911601
case OP_MAX2:for(int64_t i=0;i<n;i++){uint8_t li=(uint8_t)LV_READ(i),ri=(uint8_t)RV_READ(i);odst[i]=li>ri?li:ri;}break;
@@ -1794,7 +1804,7 @@ ray_t* exec_elementwise_binary(ray_graph_t* g, ray_op_t* op, ray_t* lhs, ray_t*
17941804
/* Div/mod: mark zero-divisor positions as null.
17951805
* The morsel loop writes 0 for b==0 but can't set bitmap nulls. */
17961806
uint16_t opc = op->opcode;
1797-
if (opc == OP_DIV || opc == OP_MOD) {
1807+
if (opc == OP_DIV || opc == OP_IDIV || opc == OP_MOD) {
17981808
if (!r_scalar) {
17991809
int8_t rt = rhs->type;
18001810
if (rt == RAY_I64 || rt == RAY_TIMESTAMP) {

src/ops/graph.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,7 @@ ray_op_t* ray_add(ray_graph_t* g, ray_op_t* a, ray_op_t* b) { return make_binary
507507
ray_op_t* ray_sub(ray_graph_t* g, ray_op_t* a, ray_op_t* b) { return make_binary(g, OP_SUB, a, b, promote(a->out_type, b->out_type)); }
508508
ray_op_t* ray_mul(ray_graph_t* g, ray_op_t* a, ray_op_t* b) { return make_binary(g, OP_MUL, a, b, promote(a->out_type, b->out_type)); }
509509
ray_op_t* ray_div(ray_graph_t* g, ray_op_t* a, ray_op_t* b) { return make_binary(g, OP_DIV, a, b, RAY_F64); }
510+
ray_op_t* ray_idiv(ray_graph_t* g, ray_op_t* a, ray_op_t* b) { return make_binary(g, OP_IDIV, a, b, RAY_I64); }
510511
ray_op_t* ray_mod(ray_graph_t* g, ray_op_t* a, ray_op_t* b) { return make_binary(g, OP_MOD, a, b, promote(a->out_type, b->out_type)); }
511512

512513
ray_op_t* ray_eq(ray_graph_t* g, ray_op_t* a, ray_op_t* b) { return make_binary(g, OP_EQ, a, b, RAY_BOOL); }

src/ops/ops.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ void ray_cancel(void);
146146
#define OP_DATE_TRUNC 46
147147
#define OP_IN 47 /* binary: col in set_vec -> BOOL */
148148
#define OP_NOT_IN 48 /* binary: col not in set_vec -> BOOL */
149+
#define OP_IDIV 49 /* binary: integer floor division -> I64 */
149150

150151
/* EXTRACT / DATE_TRUNC field identifiers */
151152
#define RAY_EXTRACT_YEAR 0
@@ -505,6 +506,7 @@ ray_op_t* ray_add(ray_graph_t* g, ray_op_t* a, ray_op_t* b);
505506
ray_op_t* ray_sub(ray_graph_t* g, ray_op_t* a, ray_op_t* b);
506507
ray_op_t* ray_mul(ray_graph_t* g, ray_op_t* a, ray_op_t* b);
507508
ray_op_t* ray_div(ray_graph_t* g, ray_op_t* a, ray_op_t* b);
509+
ray_op_t* ray_idiv(ray_graph_t* g, ray_op_t* a, ray_op_t* b);
508510
ray_op_t* ray_mod(ray_graph_t* g, ray_op_t* a, ray_op_t* b);
509511
ray_op_t* ray_eq(ray_graph_t* g, ray_op_t* a, ray_op_t* b);
510512
ray_op_t* ray_ne(ray_graph_t* g, ray_op_t* a, ray_op_t* b);

0 commit comments

Comments
 (0)