1use super::super::nan_boxing::*;
21
22#[allow(dead_code)]
24const SIMD_THRESHOLD: usize = 16;
25
26pub extern "C" fn jit_sin(value_bits: u64) -> u64 {
31 let x = if is_number(value_bits) {
32 unbox_number(value_bits)
33 } else {
34 return box_number(f64::NAN);
35 };
36 box_number(x.sin())
37}
38
39pub extern "C" fn jit_cos(value_bits: u64) -> u64 {
40 let x = if is_number(value_bits) {
41 unbox_number(value_bits)
42 } else {
43 return box_number(f64::NAN);
44 };
45 box_number(x.cos())
46}
47
48pub extern "C" fn jit_tan(value_bits: u64) -> u64 {
49 let x = if is_number(value_bits) {
50 unbox_number(value_bits)
51 } else {
52 return box_number(f64::NAN);
53 };
54 box_number(x.tan())
55}
56
57pub extern "C" fn jit_asin(value_bits: u64) -> u64 {
58 let x = if is_number(value_bits) {
59 unbox_number(value_bits)
60 } else {
61 return box_number(f64::NAN);
62 };
63 box_number(x.asin())
64}
65
66pub extern "C" fn jit_acos(value_bits: u64) -> u64 {
67 let x = if is_number(value_bits) {
68 unbox_number(value_bits)
69 } else {
70 return box_number(f64::NAN);
71 };
72 box_number(x.acos())
73}
74
75pub extern "C" fn jit_atan(value_bits: u64) -> u64 {
76 let x = if is_number(value_bits) {
77 unbox_number(value_bits)
78 } else {
79 return box_number(f64::NAN);
80 };
81 box_number(x.atan())
82}
83
84pub extern "C" fn jit_exp(value_bits: u64) -> u64 {
89 let x = if is_number(value_bits) {
90 unbox_number(value_bits)
91 } else {
92 return box_number(f64::NAN);
93 };
94 box_number(x.exp())
95}
96
97pub extern "C" fn jit_ln(value_bits: u64) -> u64 {
98 let x = if is_number(value_bits) {
99 unbox_number(value_bits)
100 } else {
101 return box_number(f64::NAN);
102 };
103 box_number(x.ln())
104}
105
106pub extern "C" fn jit_log(value_bits: u64, base_bits: u64) -> u64 {
107 let x = if is_number(value_bits) {
108 unbox_number(value_bits)
109 } else {
110 return box_number(f64::NAN);
111 };
112 let base = if is_number(base_bits) {
113 unbox_number(base_bits)
114 } else {
115 return box_number(f64::NAN);
116 };
117 box_number(x.log(base))
118}
119
120pub extern "C" fn jit_pow(base_bits: u64, exp_bits: u64) -> u64 {
125 let base = if is_number(base_bits) {
126 unbox_number(base_bits)
127 } else {
128 return box_number(f64::NAN);
129 };
130 let exp = if is_number(exp_bits) {
131 unbox_number(exp_bits)
132 } else {
133 return box_number(f64::NAN);
134 };
135 box_number(base.powf(exp))
136}
137
138pub extern "C" fn jit_generic_add(a_bits: u64, b_bits: u64) -> u64 {
144 use super::super::context::JITDuration;
145
146 if is_number(a_bits) && is_number(b_bits) {
148 return box_number(unbox_number(a_bits) + unbox_number(b_bits));
149 }
150
151 let a_kind = heap_kind(a_bits);
152 let b_kind = heap_kind(b_bits);
153
154 if a_kind == Some(HK_TIME) && b_kind == Some(HK_DURATION) {
156 let timestamp = *unsafe { jit_unbox::<i64>(a_bits) };
157 let dur = unsafe { jit_unbox::<JITDuration>(b_bits) };
158 let seconds = duration_to_seconds(dur);
159 let new_timestamp = timestamp + seconds as i64;
160 return jit_box(HK_TIME, new_timestamp);
161 }
162
163 if a_kind == Some(HK_DURATION) && b_kind == Some(HK_TIME) {
164 let timestamp = *unsafe { jit_unbox::<i64>(b_bits) };
165 let dur = unsafe { jit_unbox::<JITDuration>(a_bits) };
166 let seconds = duration_to_seconds(dur);
167 let new_timestamp = timestamp + seconds as i64;
168 return jit_box(HK_TIME, new_timestamp);
169 }
170
171 if a_kind == Some(HK_DURATION) && b_kind == Some(HK_DURATION) {
173 let a_dur = unsafe { jit_unbox::<JITDuration>(a_bits) };
174 let b_dur = unsafe { jit_unbox::<JITDuration>(b_bits) };
175 let a_secs = duration_to_seconds(a_dur);
176 let b_secs = duration_to_seconds(b_dur);
177 let total_secs = a_secs + b_secs;
178 return jit_box(
179 HK_DURATION,
180 JITDuration {
181 value: total_secs,
182 unit: 0,
183 },
184 );
185 }
186
187 if a_kind == Some(HK_STRING) && b_kind == Some(HK_STRING) {
189 let a_str = unsafe { jit_unbox::<String>(a_bits) };
190 let b_str = unsafe { jit_unbox::<String>(b_bits) };
191 let result = format!("{}{}", a_str, b_str);
192 return jit_box(HK_STRING, result);
193 }
194
195 if is_number(a_bits) || is_number(b_bits) {
197 let a_num = if is_number(a_bits) {
198 unbox_number(a_bits)
199 } else {
200 0.0
201 };
202 let b_num = if is_number(b_bits) {
203 unbox_number(b_bits)
204 } else {
205 0.0
206 };
207 return box_number(a_num + b_num);
208 }
209
210 TAG_NULL
211}
212
213pub extern "C" fn jit_generic_sub(a_bits: u64, b_bits: u64) -> u64 {
215 use super::super::context::JITDuration;
216
217 if is_number(a_bits) && is_number(b_bits) {
219 return box_number(unbox_number(a_bits) - unbox_number(b_bits));
220 }
221
222 let a_kind = heap_kind(a_bits);
223 let b_kind = heap_kind(b_bits);
224
225 if a_kind == Some(HK_TIME) && b_kind == Some(HK_DURATION) {
227 let timestamp = *unsafe { jit_unbox::<i64>(a_bits) };
228 let dur = unsafe { jit_unbox::<JITDuration>(b_bits) };
229 let seconds = duration_to_seconds(dur);
230 let new_timestamp = timestamp - seconds as i64;
231 return jit_box(HK_TIME, new_timestamp);
232 }
233
234 if a_kind == Some(HK_TIME) && b_kind == Some(HK_TIME) {
236 let a_ts = *unsafe { jit_unbox::<i64>(a_bits) };
237 let b_ts = *unsafe { jit_unbox::<i64>(b_bits) };
238 let diff_secs = (a_ts - b_ts) as f64;
239 return jit_box(
240 HK_DURATION,
241 JITDuration {
242 value: diff_secs,
243 unit: 0,
244 },
245 );
246 }
247
248 if is_number(a_bits) || is_number(b_bits) {
250 let a_num = if is_number(a_bits) {
251 unbox_number(a_bits)
252 } else {
253 0.0
254 };
255 let b_num = if is_number(b_bits) {
256 unbox_number(b_bits)
257 } else {
258 0.0
259 };
260 return box_number(a_num - b_num);
261 }
262
263 TAG_NULL
264}
265
266#[unsafe(no_mangle)]
268pub extern "C" fn jit_generic_mul(a_bits: u64, b_bits: u64) -> u64 {
269 if is_number(a_bits) && is_number(b_bits) {
271 return box_number(unbox_number(a_bits) * unbox_number(b_bits));
272 }
273
274 if is_number(a_bits) || is_number(b_bits) {
276 let a_num = if is_number(a_bits) {
277 unbox_number(a_bits)
278 } else {
279 1.0
280 };
281 let b_num = if is_number(b_bits) {
282 unbox_number(b_bits)
283 } else {
284 1.0
285 };
286 return box_number(a_num * b_num);
287 }
288
289 TAG_NULL
290}
291
292#[unsafe(no_mangle)]
294pub extern "C" fn jit_generic_div(a_bits: u64, b_bits: u64) -> u64 {
295 if is_number(a_bits) && is_number(b_bits) {
297 let b = unbox_number(b_bits);
298 return box_number(if b == 0.0 {
299 f64::NAN
300 } else {
301 unbox_number(a_bits) / b
302 });
303 }
304
305 if is_number(a_bits) || is_number(b_bits) {
307 let a_num = if is_number(a_bits) {
308 unbox_number(a_bits)
309 } else {
310 0.0
311 };
312 let b_num = if is_number(b_bits) {
313 unbox_number(b_bits)
314 } else {
315 1.0
316 };
317 return box_number(if b_num == 0.0 {
318 f64::NAN
319 } else {
320 a_num / b_num
321 });
322 }
323
324 TAG_NULL
325}
326
327#[allow(dead_code)]
329fn series_add_simd(a_bits: u64, b_bits: u64) -> u64 {
330 series_simd_binary_op(
331 a_bits,
332 b_bits,
333 super::simd::jit_simd_add,
334 super::simd::jit_simd_add_scalar,
335 )
336}
337
338#[allow(dead_code)]
340fn series_sub_simd(a_bits: u64, b_bits: u64) -> u64 {
341 series_simd_binary_op(
342 a_bits,
343 b_bits,
344 super::simd::jit_simd_sub,
345 super::simd::jit_simd_sub_scalar,
346 )
347}
348
349#[allow(dead_code)]
351fn series_mul_simd(a_bits: u64, b_bits: u64) -> u64 {
352 series_simd_binary_op(
353 a_bits,
354 b_bits,
355 super::simd::jit_simd_mul,
356 super::simd::jit_simd_mul_scalar,
357 )
358}
359
360#[allow(dead_code)]
362fn series_div_simd(a_bits: u64, b_bits: u64) -> u64 {
363 series_simd_binary_op(
364 a_bits,
365 b_bits,
366 super::simd::jit_simd_div,
367 super::simd::jit_simd_div_scalar,
368 )
369}
370
371fn series_simd_binary_op(
374 _a_bits: u64,
375 _b_bits: u64,
376 _simd_binary: extern "C" fn(*const f64, *const f64, u64) -> *mut f64,
377 _simd_scalar: extern "C" fn(*const f64, f64, u64) -> *mut f64,
378) -> u64 {
379 TAG_NULL
380}
381
382#[allow(dead_code)]
384fn series_binary_op<F>(_a_bits: u64, _b_bits: u64, _op: F) -> u64
385where
386 F: Fn(f64, f64) -> f64,
387{
388 TAG_NULL
389}
390
391pub extern "C" fn jit_series_gt(a_bits: u64, b_bits: u64) -> u64 {
394 series_comparison_op(a_bits, b_bits, |a, b| a > b)
395}
396
397pub extern "C" fn jit_series_lt(a_bits: u64, b_bits: u64) -> u64 {
398 series_comparison_op(a_bits, b_bits, |a, b| a < b)
399}
400
401pub extern "C" fn jit_series_gte(a_bits: u64, b_bits: u64) -> u64 {
402 series_comparison_op(a_bits, b_bits, |a, b| a >= b)
403}
404
405pub extern "C" fn jit_series_lte(a_bits: u64, b_bits: u64) -> u64 {
406 series_comparison_op(a_bits, b_bits, |a, b| a <= b)
407}
408
409fn series_comparison_op<F>(a_bits: u64, b_bits: u64, op: F) -> u64
411where
412 F: Fn(f64, f64) -> bool,
413{
414 if is_number(a_bits) && is_number(b_bits) {
416 let a = unbox_number(a_bits);
417 let b = unbox_number(b_bits);
418 return if op(a, b) {
419 TAG_BOOL_TRUE
420 } else {
421 TAG_BOOL_FALSE
422 };
423 }
424 TAG_BOOL_FALSE
425}
426
427pub extern "C" fn jit_generic_eq(a_bits: u64, b_bits: u64) -> u64 {
430 if is_number(a_bits) && is_number(b_bits) {
432 return if unbox_number(a_bits) == unbox_number(b_bits) {
433 TAG_BOOL_TRUE
434 } else {
435 TAG_BOOL_FALSE
436 };
437 }
438
439 if a_bits == b_bits {
441 return TAG_BOOL_TRUE;
442 }
443
444 let a_kind = heap_kind(a_bits);
446 let b_kind = heap_kind(b_bits);
447
448 if a_kind == Some(HK_STRING) && b_kind == Some(HK_STRING) {
449 let a_str = unsafe { jit_unbox::<String>(a_bits) };
450 let b_str = unsafe { jit_unbox::<String>(b_bits) };
451 return if a_str == b_str {
452 TAG_BOOL_TRUE
453 } else {
454 TAG_BOOL_FALSE
455 };
456 }
457
458 TAG_BOOL_FALSE
459}
460
461pub extern "C" fn jit_generic_neq(a_bits: u64, b_bits: u64) -> u64 {
463 if jit_generic_eq(a_bits, b_bits) == TAG_BOOL_TRUE {
464 TAG_BOOL_FALSE
465 } else {
466 TAG_BOOL_TRUE
467 }
468}
469
470fn duration_to_seconds(dur: &super::super::context::JITDuration) -> f64 {
472 match dur.unit {
473 0 => dur.value, 1 => dur.value * 60.0, 2 => dur.value * 3600.0, 3 => dur.value * 86400.0, 4 => dur.value * 604800.0, 5 => dur.value * 2592000.0, 6 => dur.value * 31536000.0, _ => dur.value,
481 }
482}
483
484#[cfg(test)]
485mod tests {
486 use super::*;
487
488 #[test]
489 fn test_scalar_add() {
490 let a = box_number(10.0);
491 let b = box_number(32.0);
492 let result = jit_generic_add(a, b);
493 assert_eq!(unbox_number(result), 42.0);
494 }
495
496 #[test]
497 fn test_scalar_sub() {
498 let a = box_number(100.0);
499 let b = box_number(58.0);
500 let result = jit_generic_sub(a, b);
501 assert_eq!(unbox_number(result), 42.0);
502 }
503
504 #[test]
505 fn test_scalar_mul() {
506 let a = box_number(6.0);
507 let b = box_number(7.0);
508 let result = jit_generic_mul(a, b);
509 assert_eq!(unbox_number(result), 42.0);
510 }
511
512 #[test]
513 fn test_scalar_div() {
514 let a = box_number(84.0);
515 let b = box_number(2.0);
516 let result = jit_generic_div(a, b);
517 assert_eq!(unbox_number(result), 42.0);
518 }
519
520 #[test]
521 fn test_scalar_div_by_zero() {
522 let a = box_number(42.0);
523 let b = box_number(0.0);
524 let result = jit_generic_div(a, b);
525 let val = unbox_number(result);
527 assert!(val.is_infinite() || val.is_nan());
528 }
529}