1use super::utils::{ARG_ANY_TWO, ARG_NUM_LENIENT_TWO, coerce_num};
5use crate::args::ArgSchema;
6use crate::function::Function;
7use crate::traits::{ArgumentHandle, FunctionContext};
8use formualizer_common::{ExcelError, LiteralValue};
9use formualizer_macros::func_caps;
10
11fn to_bitwise_int(v: &LiteralValue) -> Result<i64, ExcelError> {
14 let n = coerce_num(v)?;
15 if n < 0.0 || n != n.trunc() || n >= 281474976710656.0 {
16 return Err(ExcelError::new_num());
18 }
19 Ok(n as i64)
20}
21
22#[derive(Debug)]
26pub struct BitAndFn;
27impl Function for BitAndFn {
28 func_caps!(PURE);
29 fn name(&self) -> &'static str {
30 "BITAND"
31 }
32 fn min_args(&self) -> usize {
33 2
34 }
35 fn arg_schema(&self) -> &'static [ArgSchema] {
36 &ARG_NUM_LENIENT_TWO[..]
37 }
38 fn eval<'a, 'b, 'c>(
39 &self,
40 args: &'c [ArgumentHandle<'a, 'b>],
41 _ctx: &dyn FunctionContext<'b>,
42 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
43 let a = match args[0].value()?.into_literal() {
44 LiteralValue::Error(e) => {
45 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
46 }
47 other => match to_bitwise_int(&other) {
48 Ok(n) => n,
49 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
50 },
51 };
52 let b = match args[1].value()?.into_literal() {
53 LiteralValue::Error(e) => {
54 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
55 }
56 other => match to_bitwise_int(&other) {
57 Ok(n) => n,
58 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
59 },
60 };
61 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
62 (a & b) as f64,
63 )))
64 }
65}
66
67#[derive(Debug)]
71pub struct BitOrFn;
72impl Function for BitOrFn {
73 func_caps!(PURE);
74 fn name(&self) -> &'static str {
75 "BITOR"
76 }
77 fn min_args(&self) -> usize {
78 2
79 }
80 fn arg_schema(&self) -> &'static [ArgSchema] {
81 &ARG_NUM_LENIENT_TWO[..]
82 }
83 fn eval<'a, 'b, 'c>(
84 &self,
85 args: &'c [ArgumentHandle<'a, 'b>],
86 _ctx: &dyn FunctionContext<'b>,
87 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
88 let a = match args[0].value()?.into_literal() {
89 LiteralValue::Error(e) => {
90 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
91 }
92 other => match to_bitwise_int(&other) {
93 Ok(n) => n,
94 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
95 },
96 };
97 let b = match args[1].value()?.into_literal() {
98 LiteralValue::Error(e) => {
99 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
100 }
101 other => match to_bitwise_int(&other) {
102 Ok(n) => n,
103 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
104 },
105 };
106 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
107 (a | b) as f64,
108 )))
109 }
110}
111
112#[derive(Debug)]
116pub struct BitXorFn;
117impl Function for BitXorFn {
118 func_caps!(PURE);
119 fn name(&self) -> &'static str {
120 "BITXOR"
121 }
122 fn min_args(&self) -> usize {
123 2
124 }
125 fn arg_schema(&self) -> &'static [ArgSchema] {
126 &ARG_NUM_LENIENT_TWO[..]
127 }
128 fn eval<'a, 'b, 'c>(
129 &self,
130 args: &'c [ArgumentHandle<'a, 'b>],
131 _ctx: &dyn FunctionContext<'b>,
132 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
133 let a = match args[0].value()?.into_literal() {
134 LiteralValue::Error(e) => {
135 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
136 }
137 other => match to_bitwise_int(&other) {
138 Ok(n) => n,
139 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
140 },
141 };
142 let b = match args[1].value()?.into_literal() {
143 LiteralValue::Error(e) => {
144 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
145 }
146 other => match to_bitwise_int(&other) {
147 Ok(n) => n,
148 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
149 },
150 };
151 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
152 (a ^ b) as f64,
153 )))
154 }
155}
156
157#[derive(Debug)]
161pub struct BitLShiftFn;
162impl Function for BitLShiftFn {
163 func_caps!(PURE);
164 fn name(&self) -> &'static str {
165 "BITLSHIFT"
166 }
167 fn min_args(&self) -> usize {
168 2
169 }
170 fn arg_schema(&self) -> &'static [ArgSchema] {
171 &ARG_NUM_LENIENT_TWO[..]
172 }
173 fn eval<'a, 'b, 'c>(
174 &self,
175 args: &'c [ArgumentHandle<'a, 'b>],
176 _ctx: &dyn FunctionContext<'b>,
177 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
178 let n = match args[0].value()?.into_literal() {
179 LiteralValue::Error(e) => {
180 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
181 }
182 other => match to_bitwise_int(&other) {
183 Ok(n) => n,
184 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
185 },
186 };
187 let shift = match args[1].value()?.into_literal() {
188 LiteralValue::Error(e) => {
189 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
190 }
191 other => coerce_num(&other)? as i32,
192 };
193
194 let result = if shift >= 0 {
196 if shift >= 48 {
197 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
198 ExcelError::new_num(),
199 )));
200 }
201 let shifted = n << shift;
202 if shifted >= 281474976710656 {
204 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
205 ExcelError::new_num(),
206 )));
207 }
208 shifted
209 } else {
210 let rshift = (-shift) as u32;
211 if rshift >= 48 { 0 } else { n >> rshift }
212 };
213
214 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
215 result as f64,
216 )))
217 }
218}
219
220#[derive(Debug)]
224pub struct BitRShiftFn;
225impl Function for BitRShiftFn {
226 func_caps!(PURE);
227 fn name(&self) -> &'static str {
228 "BITRSHIFT"
229 }
230 fn min_args(&self) -> usize {
231 2
232 }
233 fn arg_schema(&self) -> &'static [ArgSchema] {
234 &ARG_NUM_LENIENT_TWO[..]
235 }
236 fn eval<'a, 'b, 'c>(
237 &self,
238 args: &'c [ArgumentHandle<'a, 'b>],
239 _ctx: &dyn FunctionContext<'b>,
240 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
241 let n = match args[0].value()?.into_literal() {
242 LiteralValue::Error(e) => {
243 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
244 }
245 other => match to_bitwise_int(&other) {
246 Ok(n) => n,
247 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
248 },
249 };
250 let shift = match args[1].value()?.into_literal() {
251 LiteralValue::Error(e) => {
252 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
253 }
254 other => coerce_num(&other)? as i32,
255 };
256
257 let result = if shift >= 0 {
259 if shift >= 48 { 0 } else { n >> shift }
260 } else {
261 let lshift = (-shift) as u32;
262 if lshift >= 48 {
263 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
264 ExcelError::new_num(),
265 )));
266 }
267 let shifted = n << lshift;
268 if shifted >= 281474976710656 {
270 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
271 ExcelError::new_num(),
272 )));
273 }
274 shifted
275 };
276
277 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
278 result as f64,
279 )))
280 }
281}
282
283use super::utils::ARG_ANY_ONE;
286
287fn coerce_base_text(v: &LiteralValue) -> Result<String, ExcelError> {
289 match v {
290 LiteralValue::Text(s) => Ok(s.clone()),
291 LiteralValue::Int(i) => Ok(i.to_string()),
292 LiteralValue::Number(n) => Ok((*n as i64).to_string()),
293 LiteralValue::Error(e) => Err(e.clone()),
294 _ => Err(ExcelError::new_value()),
295 }
296}
297
298#[derive(Debug)]
300pub struct Bin2DecFn;
301impl Function for Bin2DecFn {
302 func_caps!(PURE);
303 fn name(&self) -> &'static str {
304 "BIN2DEC"
305 }
306 fn min_args(&self) -> usize {
307 1
308 }
309 fn arg_schema(&self) -> &'static [ArgSchema] {
310 &ARG_ANY_ONE[..]
311 }
312 fn eval<'a, 'b, 'c>(
313 &self,
314 args: &'c [ArgumentHandle<'a, 'b>],
315 _ctx: &dyn FunctionContext<'b>,
316 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
317 let text = match args[0].value()?.into_literal() {
318 LiteralValue::Error(e) => {
319 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
320 }
321 other => match coerce_base_text(&other) {
322 Ok(s) => s,
323 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
324 },
325 };
326
327 if text.len() > 10 || !text.chars().all(|c| c == '0' || c == '1') {
329 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
330 ExcelError::new_num(),
331 )));
332 }
333
334 let result = if text.len() == 10 && text.starts_with('1') {
336 let val = i64::from_str_radix(&text, 2).unwrap_or(0);
338 val - 1024 } else {
340 i64::from_str_radix(&text, 2).unwrap_or(0)
341 };
342
343 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
344 result as f64,
345 )))
346 }
347}
348
349#[derive(Debug)]
351pub struct Dec2BinFn;
352impl Function for Dec2BinFn {
353 func_caps!(PURE);
354 fn name(&self) -> &'static str {
355 "DEC2BIN"
356 }
357 fn min_args(&self) -> usize {
358 1
359 }
360 fn variadic(&self) -> bool {
361 true
362 }
363 fn arg_schema(&self) -> &'static [ArgSchema] {
364 &ARG_NUM_LENIENT_TWO[..]
365 }
366 fn eval<'a, 'b, 'c>(
367 &self,
368 args: &'c [ArgumentHandle<'a, 'b>],
369 _ctx: &dyn FunctionContext<'b>,
370 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
371 let n = match args[0].value()?.into_literal() {
372 LiteralValue::Error(e) => {
373 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
374 }
375 other => coerce_num(&other)? as i64,
376 };
377
378 if n < -512 || n > 511 {
380 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
381 ExcelError::new_num(),
382 )));
383 }
384
385 let places = if args.len() > 1 {
386 match args[1].value()?.into_literal() {
387 LiteralValue::Error(e) => {
388 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
389 }
390 other => Some(coerce_num(&other)? as usize),
391 }
392 } else {
393 None
394 };
395
396 let binary = if n >= 0 {
397 format!("{:b}", n)
398 } else {
399 format!("{:010b}", (n + 1024) as u64)
401 };
402
403 let result = if let Some(p) = places {
404 if p < binary.len() || p > 10 {
405 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
406 ExcelError::new_num(),
407 )));
408 }
409 format!("{:0>width$}", binary, width = p)
410 } else {
411 binary
412 };
413
414 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
415 }
416}
417
418#[derive(Debug)]
420pub struct Hex2DecFn;
421impl Function for Hex2DecFn {
422 func_caps!(PURE);
423 fn name(&self) -> &'static str {
424 "HEX2DEC"
425 }
426 fn min_args(&self) -> usize {
427 1
428 }
429 fn arg_schema(&self) -> &'static [ArgSchema] {
430 &ARG_ANY_ONE[..]
431 }
432 fn eval<'a, 'b, 'c>(
433 &self,
434 args: &'c [ArgumentHandle<'a, 'b>],
435 _ctx: &dyn FunctionContext<'b>,
436 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
437 let text = match args[0].value()?.into_literal() {
438 LiteralValue::Error(e) => {
439 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
440 }
441 other => match coerce_base_text(&other) {
442 Ok(s) => s.to_uppercase(),
443 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
444 },
445 };
446
447 if text.len() > 10 || !text.chars().all(|c| c.is_ascii_hexdigit()) {
449 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
450 ExcelError::new_num(),
451 )));
452 }
453
454 let result = if text.len() == 10 && text.starts_with(|c| c >= '8') {
455 let val = i64::from_str_radix(&text, 16).unwrap_or(0);
457 val - (1i64 << 40)
458 } else {
459 i64::from_str_radix(&text, 16).unwrap_or(0)
460 };
461
462 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
463 result as f64,
464 )))
465 }
466}
467
468#[derive(Debug)]
470pub struct Dec2HexFn;
471impl Function for Dec2HexFn {
472 func_caps!(PURE);
473 fn name(&self) -> &'static str {
474 "DEC2HEX"
475 }
476 fn min_args(&self) -> usize {
477 1
478 }
479 fn variadic(&self) -> bool {
480 true
481 }
482 fn arg_schema(&self) -> &'static [ArgSchema] {
483 &ARG_NUM_LENIENT_TWO[..]
484 }
485 fn eval<'a, 'b, 'c>(
486 &self,
487 args: &'c [ArgumentHandle<'a, 'b>],
488 _ctx: &dyn FunctionContext<'b>,
489 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
490 let n = match args[0].value()?.into_literal() {
491 LiteralValue::Error(e) => {
492 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
493 }
494 other => coerce_num(&other)? as i64,
495 };
496
497 if n < -(1i64 << 39) || n > (1i64 << 39) - 1 {
499 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
500 ExcelError::new_num(),
501 )));
502 }
503
504 let places = if args.len() > 1 {
505 match args[1].value()?.into_literal() {
506 LiteralValue::Error(e) => {
507 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
508 }
509 other => Some(coerce_num(&other)? as usize),
510 }
511 } else {
512 None
513 };
514
515 let hex = if n >= 0 {
516 format!("{:X}", n)
517 } else {
518 format!("{:010X}", (n + (1i64 << 40)) as u64)
520 };
521
522 let result = if let Some(p) = places {
523 if p < hex.len() || p > 10 {
524 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
525 ExcelError::new_num(),
526 )));
527 }
528 format!("{:0>width$}", hex, width = p)
529 } else {
530 hex
531 };
532
533 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
534 }
535}
536
537#[derive(Debug)]
539pub struct Oct2DecFn;
540impl Function for Oct2DecFn {
541 func_caps!(PURE);
542 fn name(&self) -> &'static str {
543 "OCT2DEC"
544 }
545 fn min_args(&self) -> usize {
546 1
547 }
548 fn arg_schema(&self) -> &'static [ArgSchema] {
549 &ARG_ANY_ONE[..]
550 }
551 fn eval<'a, 'b, 'c>(
552 &self,
553 args: &'c [ArgumentHandle<'a, 'b>],
554 _ctx: &dyn FunctionContext<'b>,
555 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
556 let text = match args[0].value()?.into_literal() {
557 LiteralValue::Error(e) => {
558 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
559 }
560 other => match coerce_base_text(&other) {
561 Ok(s) => s,
562 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
563 },
564 };
565
566 if text.len() > 10 || !text.chars().all(|c| c >= '0' && c <= '7') {
568 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
569 ExcelError::new_num(),
570 )));
571 }
572
573 let result = if text.len() == 10 && text.starts_with(|c| c >= '4') {
574 let val = i64::from_str_radix(&text, 8).unwrap_or(0);
576 val - (1i64 << 30)
577 } else {
578 i64::from_str_radix(&text, 8).unwrap_or(0)
579 };
580
581 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
582 result as f64,
583 )))
584 }
585}
586
587#[derive(Debug)]
589pub struct Dec2OctFn;
590impl Function for Dec2OctFn {
591 func_caps!(PURE);
592 fn name(&self) -> &'static str {
593 "DEC2OCT"
594 }
595 fn min_args(&self) -> usize {
596 1
597 }
598 fn variadic(&self) -> bool {
599 true
600 }
601 fn arg_schema(&self) -> &'static [ArgSchema] {
602 &ARG_NUM_LENIENT_TWO[..]
603 }
604 fn eval<'a, 'b, 'c>(
605 &self,
606 args: &'c [ArgumentHandle<'a, 'b>],
607 _ctx: &dyn FunctionContext<'b>,
608 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
609 let n = match args[0].value()?.into_literal() {
610 LiteralValue::Error(e) => {
611 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
612 }
613 other => coerce_num(&other)? as i64,
614 };
615
616 if n < -(1i64 << 29) || n > (1i64 << 29) - 1 {
618 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
619 ExcelError::new_num(),
620 )));
621 }
622
623 let places = if args.len() > 1 {
624 match args[1].value()?.into_literal() {
625 LiteralValue::Error(e) => {
626 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
627 }
628 other => Some(coerce_num(&other)? as usize),
629 }
630 } else {
631 None
632 };
633
634 let octal = if n >= 0 {
635 format!("{:o}", n)
636 } else {
637 format!("{:010o}", (n + (1i64 << 30)) as u64)
639 };
640
641 let result = if let Some(p) = places {
642 if p < octal.len() || p > 10 {
643 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
644 ExcelError::new_num(),
645 )));
646 }
647 format!("{:0>width$}", octal, width = p)
648 } else {
649 octal
650 };
651
652 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
653 }
654}
655
656#[derive(Debug)]
660pub struct Bin2HexFn;
661impl Function for Bin2HexFn {
662 func_caps!(PURE);
663 fn name(&self) -> &'static str {
664 "BIN2HEX"
665 }
666 fn min_args(&self) -> usize {
667 1
668 }
669 fn variadic(&self) -> bool {
670 true
671 }
672 fn arg_schema(&self) -> &'static [ArgSchema] {
673 &ARG_NUM_LENIENT_TWO[..]
674 }
675 fn eval<'a, 'b, 'c>(
676 &self,
677 args: &'c [ArgumentHandle<'a, 'b>],
678 _ctx: &dyn FunctionContext<'b>,
679 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
680 let text = match args[0].value()?.into_literal() {
681 LiteralValue::Error(e) => {
682 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
683 }
684 other => match coerce_base_text(&other) {
685 Ok(s) => s,
686 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
687 },
688 };
689
690 if text.len() > 10 || !text.chars().all(|c| c == '0' || c == '1') {
691 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
692 ExcelError::new_num(),
693 )));
694 }
695
696 let dec = if text.len() == 10 && text.starts_with('1') {
698 let val = i64::from_str_radix(&text, 2).unwrap_or(0);
699 val - 1024
700 } else {
701 i64::from_str_radix(&text, 2).unwrap_or(0)
702 };
703
704 let places = if args.len() > 1 {
705 match args[1].value()?.into_literal() {
706 LiteralValue::Error(e) => {
707 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
708 }
709 other => Some(coerce_num(&other)? as usize),
710 }
711 } else {
712 None
713 };
714
715 let hex = if dec >= 0 {
716 format!("{:X}", dec)
717 } else {
718 format!("{:010X}", (dec + (1i64 << 40)) as u64)
719 };
720
721 let result = if let Some(p) = places {
722 if p < hex.len() || p > 10 {
723 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
724 ExcelError::new_num(),
725 )));
726 }
727 format!("{:0>width$}", hex, width = p)
728 } else {
729 hex
730 };
731
732 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
733 }
734}
735
736#[derive(Debug)]
738pub struct Hex2BinFn;
739impl Function for Hex2BinFn {
740 func_caps!(PURE);
741 fn name(&self) -> &'static str {
742 "HEX2BIN"
743 }
744 fn min_args(&self) -> usize {
745 1
746 }
747 fn variadic(&self) -> bool {
748 true
749 }
750 fn arg_schema(&self) -> &'static [ArgSchema] {
751 &ARG_ANY_TWO[..]
752 }
753 fn eval<'a, 'b, 'c>(
754 &self,
755 args: &'c [ArgumentHandle<'a, 'b>],
756 _ctx: &dyn FunctionContext<'b>,
757 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
758 let text = match args[0].value()?.into_literal() {
759 LiteralValue::Error(e) => {
760 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
761 }
762 other => match coerce_base_text(&other) {
763 Ok(s) => s.to_uppercase(),
764 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
765 },
766 };
767
768 if text.len() > 10 || !text.chars().all(|c| c.is_ascii_hexdigit()) {
769 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
770 ExcelError::new_num(),
771 )));
772 }
773
774 let dec = if text.len() == 10 && text.starts_with(|c| c >= '8') {
776 let val = i64::from_str_radix(&text, 16).unwrap_or(0);
777 val - (1i64 << 40)
778 } else {
779 i64::from_str_radix(&text, 16).unwrap_or(0)
780 };
781
782 if dec < -512 || dec > 511 {
784 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
785 ExcelError::new_num(),
786 )));
787 }
788
789 let places = if args.len() > 1 {
790 match args[1].value()?.into_literal() {
791 LiteralValue::Error(e) => {
792 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
793 }
794 other => Some(coerce_num(&other)? as usize),
795 }
796 } else {
797 None
798 };
799
800 let binary = if dec >= 0 {
801 format!("{:b}", dec)
802 } else {
803 format!("{:010b}", (dec + 1024) as u64)
804 };
805
806 let result = if let Some(p) = places {
807 if p < binary.len() || p > 10 {
808 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
809 ExcelError::new_num(),
810 )));
811 }
812 format!("{:0>width$}", binary, width = p)
813 } else {
814 binary
815 };
816
817 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
818 }
819}
820
821#[derive(Debug)]
823pub struct Bin2OctFn;
824impl Function for Bin2OctFn {
825 func_caps!(PURE);
826 fn name(&self) -> &'static str {
827 "BIN2OCT"
828 }
829 fn min_args(&self) -> usize {
830 1
831 }
832 fn variadic(&self) -> bool {
833 true
834 }
835 fn arg_schema(&self) -> &'static [ArgSchema] {
836 &ARG_NUM_LENIENT_TWO[..]
837 }
838 fn eval<'a, 'b, 'c>(
839 &self,
840 args: &'c [ArgumentHandle<'a, 'b>],
841 _ctx: &dyn FunctionContext<'b>,
842 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
843 let text = match args[0].value()?.into_literal() {
844 LiteralValue::Error(e) => {
845 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
846 }
847 other => match coerce_base_text(&other) {
848 Ok(s) => s,
849 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
850 },
851 };
852
853 if text.len() > 10 || !text.chars().all(|c| c == '0' || c == '1') {
854 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
855 ExcelError::new_num(),
856 )));
857 }
858
859 let dec = if text.len() == 10 && text.starts_with('1') {
860 let val = i64::from_str_radix(&text, 2).unwrap_or(0);
861 val - 1024
862 } else {
863 i64::from_str_radix(&text, 2).unwrap_or(0)
864 };
865
866 let places = if args.len() > 1 {
867 match args[1].value()?.into_literal() {
868 LiteralValue::Error(e) => {
869 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
870 }
871 other => Some(coerce_num(&other)? as usize),
872 }
873 } else {
874 None
875 };
876
877 let octal = if dec >= 0 {
878 format!("{:o}", dec)
879 } else {
880 format!("{:010o}", (dec + (1i64 << 30)) as u64)
881 };
882
883 let result = if let Some(p) = places {
884 if p < octal.len() || p > 10 {
885 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
886 ExcelError::new_num(),
887 )));
888 }
889 format!("{:0>width$}", octal, width = p)
890 } else {
891 octal
892 };
893
894 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
895 }
896}
897
898#[derive(Debug)]
900pub struct Oct2BinFn;
901impl Function for Oct2BinFn {
902 func_caps!(PURE);
903 fn name(&self) -> &'static str {
904 "OCT2BIN"
905 }
906 fn min_args(&self) -> usize {
907 1
908 }
909 fn variadic(&self) -> bool {
910 true
911 }
912 fn arg_schema(&self) -> &'static [ArgSchema] {
913 &ARG_NUM_LENIENT_TWO[..]
914 }
915 fn eval<'a, 'b, 'c>(
916 &self,
917 args: &'c [ArgumentHandle<'a, 'b>],
918 _ctx: &dyn FunctionContext<'b>,
919 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
920 let text = match args[0].value()?.into_literal() {
921 LiteralValue::Error(e) => {
922 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
923 }
924 other => match coerce_base_text(&other) {
925 Ok(s) => s,
926 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
927 },
928 };
929
930 if text.len() > 10 || !text.chars().all(|c| c >= '0' && c <= '7') {
931 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
932 ExcelError::new_num(),
933 )));
934 }
935
936 let dec = if text.len() == 10 && text.starts_with(|c| c >= '4') {
937 let val = i64::from_str_radix(&text, 8).unwrap_or(0);
938 val - (1i64 << 30)
939 } else {
940 i64::from_str_radix(&text, 8).unwrap_or(0)
941 };
942
943 if dec < -512 || dec > 511 {
945 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
946 ExcelError::new_num(),
947 )));
948 }
949
950 let places = if args.len() > 1 {
951 match args[1].value()?.into_literal() {
952 LiteralValue::Error(e) => {
953 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
954 }
955 other => Some(coerce_num(&other)? as usize),
956 }
957 } else {
958 None
959 };
960
961 let binary = if dec >= 0 {
962 format!("{:b}", dec)
963 } else {
964 format!("{:010b}", (dec + 1024) as u64)
965 };
966
967 let result = if let Some(p) = places {
968 if p < binary.len() || p > 10 {
969 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
970 ExcelError::new_num(),
971 )));
972 }
973 format!("{:0>width$}", binary, width = p)
974 } else {
975 binary
976 };
977
978 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
979 }
980}
981
982#[derive(Debug)]
984pub struct Hex2OctFn;
985impl Function for Hex2OctFn {
986 func_caps!(PURE);
987 fn name(&self) -> &'static str {
988 "HEX2OCT"
989 }
990 fn min_args(&self) -> usize {
991 1
992 }
993 fn variadic(&self) -> bool {
994 true
995 }
996 fn arg_schema(&self) -> &'static [ArgSchema] {
997 &ARG_ANY_TWO[..]
998 }
999 fn eval<'a, 'b, 'c>(
1000 &self,
1001 args: &'c [ArgumentHandle<'a, 'b>],
1002 _ctx: &dyn FunctionContext<'b>,
1003 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1004 let text = match args[0].value()?.into_literal() {
1005 LiteralValue::Error(e) => {
1006 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1007 }
1008 other => match coerce_base_text(&other) {
1009 Ok(s) => s.to_uppercase(),
1010 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1011 },
1012 };
1013
1014 if text.len() > 10 || !text.chars().all(|c| c.is_ascii_hexdigit()) {
1015 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
1016 ExcelError::new_num(),
1017 )));
1018 }
1019
1020 let dec = if text.len() == 10 && text.starts_with(|c| c >= '8') {
1021 let val = i64::from_str_radix(&text, 16).unwrap_or(0);
1022 val - (1i64 << 40)
1023 } else {
1024 i64::from_str_radix(&text, 16).unwrap_or(0)
1025 };
1026
1027 if dec < -(1i64 << 29) || dec > (1i64 << 29) - 1 {
1029 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
1030 ExcelError::new_num(),
1031 )));
1032 }
1033
1034 let places = if args.len() > 1 {
1035 match args[1].value()?.into_literal() {
1036 LiteralValue::Error(e) => {
1037 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1038 }
1039 other => Some(coerce_num(&other)? as usize),
1040 }
1041 } else {
1042 None
1043 };
1044
1045 let octal = if dec >= 0 {
1046 format!("{:o}", dec)
1047 } else {
1048 format!("{:010o}", (dec + (1i64 << 30)) as u64)
1049 };
1050
1051 let result = if let Some(p) = places {
1052 if p < octal.len() || p > 10 {
1053 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
1054 ExcelError::new_num(),
1055 )));
1056 }
1057 format!("{:0>width$}", octal, width = p)
1058 } else {
1059 octal
1060 };
1061
1062 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
1063 }
1064}
1065
1066#[derive(Debug)]
1068pub struct Oct2HexFn;
1069impl Function for Oct2HexFn {
1070 func_caps!(PURE);
1071 fn name(&self) -> &'static str {
1072 "OCT2HEX"
1073 }
1074 fn min_args(&self) -> usize {
1075 1
1076 }
1077 fn variadic(&self) -> bool {
1078 true
1079 }
1080 fn arg_schema(&self) -> &'static [ArgSchema] {
1081 &ARG_NUM_LENIENT_TWO[..]
1082 }
1083 fn eval<'a, 'b, 'c>(
1084 &self,
1085 args: &'c [ArgumentHandle<'a, 'b>],
1086 _ctx: &dyn FunctionContext<'b>,
1087 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1088 let text = match args[0].value()?.into_literal() {
1089 LiteralValue::Error(e) => {
1090 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1091 }
1092 other => match coerce_base_text(&other) {
1093 Ok(s) => s,
1094 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1095 },
1096 };
1097
1098 if text.len() > 10 || !text.chars().all(|c| c >= '0' && c <= '7') {
1099 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
1100 ExcelError::new_num(),
1101 )));
1102 }
1103
1104 let dec = if text.len() == 10 && text.starts_with(|c| c >= '4') {
1105 let val = i64::from_str_radix(&text, 8).unwrap_or(0);
1106 val - (1i64 << 30)
1107 } else {
1108 i64::from_str_radix(&text, 8).unwrap_or(0)
1109 };
1110
1111 let places = if args.len() > 1 {
1112 match args[1].value()?.into_literal() {
1113 LiteralValue::Error(e) => {
1114 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1115 }
1116 other => Some(coerce_num(&other)? as usize),
1117 }
1118 } else {
1119 None
1120 };
1121
1122 let hex = if dec >= 0 {
1123 format!("{:X}", dec)
1124 } else {
1125 format!("{:010X}", (dec + (1i64 << 40)) as u64)
1126 };
1127
1128 let result = if let Some(p) = places {
1129 if p < hex.len() || p > 10 {
1130 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
1131 ExcelError::new_num(),
1132 )));
1133 }
1134 format!("{:0>width$}", hex, width = p)
1135 } else {
1136 hex
1137 };
1138
1139 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
1140 }
1141}
1142
1143#[derive(Debug)]
1147pub struct DeltaFn;
1148impl Function for DeltaFn {
1149 func_caps!(PURE);
1150 fn name(&self) -> &'static str {
1151 "DELTA"
1152 }
1153 fn min_args(&self) -> usize {
1154 1
1155 }
1156 fn variadic(&self) -> bool {
1157 true
1158 }
1159 fn arg_schema(&self) -> &'static [ArgSchema] {
1160 &ARG_NUM_LENIENT_TWO[..]
1161 }
1162 fn eval<'a, 'b, 'c>(
1163 &self,
1164 args: &'c [ArgumentHandle<'a, 'b>],
1165 _ctx: &dyn FunctionContext<'b>,
1166 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1167 let n1 = match args[0].value()?.into_literal() {
1168 LiteralValue::Error(e) => {
1169 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1170 }
1171 other => coerce_num(&other)?,
1172 };
1173 let n2 = if args.len() > 1 {
1174 match args[1].value()?.into_literal() {
1175 LiteralValue::Error(e) => {
1176 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1177 }
1178 other => coerce_num(&other)?,
1179 }
1180 } else {
1181 0.0
1182 };
1183
1184 let result = if (n1 - n2).abs() < 1e-12 { 1.0 } else { 0.0 };
1185 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
1186 result,
1187 )))
1188 }
1189}
1190
1191#[derive(Debug)]
1193pub struct GestepFn;
1194impl Function for GestepFn {
1195 func_caps!(PURE);
1196 fn name(&self) -> &'static str {
1197 "GESTEP"
1198 }
1199 fn min_args(&self) -> usize {
1200 1
1201 }
1202 fn variadic(&self) -> bool {
1203 true
1204 }
1205 fn arg_schema(&self) -> &'static [ArgSchema] {
1206 &ARG_NUM_LENIENT_TWO[..]
1207 }
1208 fn eval<'a, 'b, 'c>(
1209 &self,
1210 args: &'c [ArgumentHandle<'a, 'b>],
1211 _ctx: &dyn FunctionContext<'b>,
1212 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1213 let n = match args[0].value()?.into_literal() {
1214 LiteralValue::Error(e) => {
1215 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1216 }
1217 other => coerce_num(&other)?,
1218 };
1219 let step = if args.len() > 1 {
1220 match args[1].value()?.into_literal() {
1221 LiteralValue::Error(e) => {
1222 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1223 }
1224 other => coerce_num(&other)?,
1225 }
1226 } else {
1227 0.0
1228 };
1229
1230 let result = if n >= step { 1.0 } else { 0.0 };
1231 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
1232 result,
1233 )))
1234 }
1235}
1236
1237fn erf_approx(x: f64) -> f64 {
1244 let ax = x.abs();
1245
1246 if ax < 0.5 {
1248 const P: [f64; 5] = [
1250 3.20937758913846947e+03,
1251 3.77485237685302021e+02,
1252 1.13864154151050156e+02,
1253 3.16112374387056560e+00,
1254 1.85777706184603153e-01,
1255 ];
1256 const Q: [f64; 5] = [
1257 2.84423748127893300e+03,
1258 1.28261652607737228e+03,
1259 2.44024637934444173e+02,
1260 2.36012909523441209e+01,
1261 1.00000000000000000e+00,
1262 ];
1263
1264 let x2 = x * x;
1265 let p_val = P[4];
1266 let p_val = p_val * x2 + P[3];
1267 let p_val = p_val * x2 + P[2];
1268 let p_val = p_val * x2 + P[1];
1269 let p_val = p_val * x2 + P[0];
1270
1271 let q_val = Q[4];
1272 let q_val = q_val * x2 + Q[3];
1273 let q_val = q_val * x2 + Q[2];
1274 let q_val = q_val * x2 + Q[1];
1275 let q_val = q_val * x2 + Q[0];
1276
1277 return x * p_val / q_val;
1278 }
1279
1280 if ax < 4.0 {
1282 let erfc_val = erfc_mid(ax);
1283 return if x > 0.0 {
1284 1.0 - erfc_val
1285 } else {
1286 erfc_val - 1.0
1287 };
1288 }
1289
1290 let erfc_val = erfc_large(ax);
1292 if x > 0.0 {
1293 1.0 - erfc_val
1294 } else {
1295 erfc_val - 1.0
1296 }
1297}
1298
1299fn erfc_mid(x: f64) -> f64 {
1301 const P: [f64; 9] = [
1302 1.23033935479799725e+03,
1303 2.05107837782607147e+03,
1304 1.71204761263407058e+03,
1305 8.81952221241769090e+02,
1306 2.98635138197400131e+02,
1307 6.61191906371416295e+01,
1308 8.88314979438837594e+00,
1309 5.64188496988670089e-01,
1310 2.15311535474403846e-08,
1311 ];
1312 const Q: [f64; 9] = [
1313 1.23033935480374942e+03,
1314 3.43936767414372164e+03,
1315 4.36261909014324716e+03,
1316 3.29079923573345963e+03,
1317 1.62138957456669019e+03,
1318 5.37181101862009858e+02,
1319 1.17693950891312499e+02,
1320 1.57449261107098347e+01,
1321 1.00000000000000000e+00,
1322 ];
1323
1324 let p_val = P[8];
1325 let p_val = p_val * x + P[7];
1326 let p_val = p_val * x + P[6];
1327 let p_val = p_val * x + P[5];
1328 let p_val = p_val * x + P[4];
1329 let p_val = p_val * x + P[3];
1330 let p_val = p_val * x + P[2];
1331 let p_val = p_val * x + P[1];
1332 let p_val = p_val * x + P[0];
1333
1334 let q_val = Q[8];
1335 let q_val = q_val * x + Q[7];
1336 let q_val = q_val * x + Q[6];
1337 let q_val = q_val * x + Q[5];
1338 let q_val = q_val * x + Q[4];
1339 let q_val = q_val * x + Q[3];
1340 let q_val = q_val * x + Q[2];
1341 let q_val = q_val * x + Q[1];
1342 let q_val = q_val * x + Q[0];
1343
1344 (-x * x).exp() * p_val / q_val
1345}
1346
1347fn erfc_large(x: f64) -> f64 {
1349 const P: [f64; 6] = [
1350 6.58749161529837803e-04,
1351 1.60837851487422766e-02,
1352 1.25781726111229246e-01,
1353 3.60344899949804439e-01,
1354 3.05326634961232344e-01,
1355 1.63153871373020978e-02,
1356 ];
1357 const Q: [f64; 6] = [
1358 2.33520497626869185e-03,
1359 6.05183413124413191e-02,
1360 5.27905102951428412e-01,
1361 1.87295284992346047e+00,
1362 2.56852019228982242e+00,
1363 1.00000000000000000e+00,
1364 ];
1365
1366 let x2 = x * x;
1367 let inv_x2 = 1.0 / x2;
1368
1369 let p_val = P[5];
1370 let p_val = p_val * inv_x2 + P[4];
1371 let p_val = p_val * inv_x2 + P[3];
1372 let p_val = p_val * inv_x2 + P[2];
1373 let p_val = p_val * inv_x2 + P[1];
1374 let p_val = p_val * inv_x2 + P[0];
1375
1376 let q_val = Q[5];
1377 let q_val = q_val * inv_x2 + Q[4];
1378 let q_val = q_val * inv_x2 + Q[3];
1379 let q_val = q_val * inv_x2 + Q[2];
1380 let q_val = q_val * inv_x2 + Q[1];
1381 let q_val = q_val * inv_x2 + Q[0];
1382
1383 const FRAC_1_SQRT_PI: f64 = 0.5641895835477563;
1385 (-x2).exp() / x * (FRAC_1_SQRT_PI + inv_x2 * p_val / q_val)
1386}
1387
1388fn erfc_direct(x: f64) -> f64 {
1390 if x < 0.0 {
1391 return 2.0 - erfc_direct(-x);
1392 }
1393 if x < 0.5 {
1394 return 1.0 - erf_approx(x);
1395 }
1396 if x < 4.0 {
1397 return erfc_mid(x);
1398 }
1399 erfc_large(x)
1400}
1401
1402#[derive(Debug)]
1406pub struct ErfFn;
1407impl Function for ErfFn {
1408 func_caps!(PURE);
1409 fn name(&self) -> &'static str {
1410 "ERF"
1411 }
1412 fn min_args(&self) -> usize {
1413 1
1414 }
1415 fn variadic(&self) -> bool {
1416 true
1417 }
1418 fn arg_schema(&self) -> &'static [ArgSchema] {
1419 &ARG_NUM_LENIENT_TWO[..]
1420 }
1421 fn eval<'a, 'b, 'c>(
1422 &self,
1423 args: &'c [ArgumentHandle<'a, 'b>],
1424 _ctx: &dyn FunctionContext<'b>,
1425 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1426 let lower = match args[0].value()?.into_literal() {
1427 LiteralValue::Error(e) => {
1428 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1429 }
1430 other => coerce_num(&other)?,
1431 };
1432
1433 let result = if args.len() > 1 {
1434 let upper = match args[1].value()?.into_literal() {
1436 LiteralValue::Error(e) => {
1437 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1438 }
1439 other => coerce_num(&other)?,
1440 };
1441 erf_approx(upper) - erf_approx(lower)
1442 } else {
1443 erf_approx(lower)
1445 };
1446
1447 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
1448 result,
1449 )))
1450 }
1451}
1452
1453#[derive(Debug)]
1455pub struct ErfcFn;
1456impl Function for ErfcFn {
1457 func_caps!(PURE);
1458 fn name(&self) -> &'static str {
1459 "ERFC"
1460 }
1461 fn min_args(&self) -> usize {
1462 1
1463 }
1464 fn arg_schema(&self) -> &'static [ArgSchema] {
1465 &ARG_ANY_ONE[..]
1466 }
1467 fn eval<'a, 'b, 'c>(
1468 &self,
1469 args: &'c [ArgumentHandle<'a, 'b>],
1470 _ctx: &dyn FunctionContext<'b>,
1471 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1472 let x = match args[0].value()?.into_literal() {
1473 LiteralValue::Error(e) => {
1474 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1475 }
1476 other => coerce_num(&other)?,
1477 };
1478
1479 let result = erfc_direct(x);
1480 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
1481 result,
1482 )))
1483 }
1484}
1485
1486#[derive(Debug)]
1488pub struct ErfPreciseFn;
1489impl Function for ErfPreciseFn {
1490 func_caps!(PURE);
1491 fn name(&self) -> &'static str {
1492 "ERF.PRECISE"
1493 }
1494 fn min_args(&self) -> usize {
1495 1
1496 }
1497 fn arg_schema(&self) -> &'static [ArgSchema] {
1498 &ARG_ANY_ONE[..]
1499 }
1500 fn eval<'a, 'b, 'c>(
1501 &self,
1502 args: &'c [ArgumentHandle<'a, 'b>],
1503 _ctx: &dyn FunctionContext<'b>,
1504 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1505 let x = match args[0].value()?.into_literal() {
1506 LiteralValue::Error(e) => {
1507 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1508 }
1509 other => coerce_num(&other)?,
1510 };
1511
1512 let result = erf_approx(x);
1513 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
1514 result,
1515 )))
1516 }
1517}
1518
1519fn parse_complex(s: &str) -> Result<(f64, f64, char), ExcelError> {
1524 let s = s.trim();
1525 if s.is_empty() {
1526 return Err(ExcelError::new_num());
1527 }
1528
1529 let suffix = if s.ends_with('i') || s.ends_with('I') {
1531 'i'
1532 } else if s.ends_with('j') || s.ends_with('J') {
1533 'j'
1534 } else {
1535 let real: f64 = s.parse().map_err(|_| ExcelError::new_num())?;
1537 return Ok((real, 0.0, 'i'));
1538 };
1539
1540 let s = &s[..s.len() - 1];
1542
1543 if s.is_empty() || s == "+" {
1545 return Ok((0.0, 1.0, suffix));
1546 }
1547 if s == "-" {
1548 return Ok((0.0, -1.0, suffix));
1549 }
1550
1551 let mut split_pos = None;
1554 let bytes = s.as_bytes();
1555
1556 for i in (1..bytes.len()).rev() {
1557 let c = bytes[i] as char;
1558 if c == '+' || c == '-' {
1559 if i > 0 {
1561 let prev = bytes[i - 1] as char;
1562 if prev == 'e' || prev == 'E' {
1563 continue;
1564 }
1565 }
1566 split_pos = Some(i);
1567 break;
1568 }
1569 }
1570
1571 match split_pos {
1572 Some(pos) => {
1573 let real_str = &s[..pos];
1575 let imag_str = &s[pos..];
1576
1577 let real: f64 = if real_str.is_empty() {
1578 0.0
1579 } else {
1580 real_str.parse().map_err(|_| ExcelError::new_num())?
1581 };
1582
1583 let imag: f64 = if imag_str == "+" {
1585 1.0
1586 } else if imag_str == "-" {
1587 -1.0
1588 } else {
1589 imag_str.parse().map_err(|_| ExcelError::new_num())?
1590 };
1591
1592 Ok((real, imag, suffix))
1593 }
1594 None => {
1595 let imag: f64 = s.parse().map_err(|_| ExcelError::new_num())?;
1597 Ok((0.0, imag, suffix))
1598 }
1599 }
1600}
1601
1602fn clean_float(val: f64) -> f64 {
1604 let rounded = val.round();
1605 if (val - rounded).abs() < 1e-10 {
1606 rounded
1607 } else {
1608 val
1609 }
1610}
1611
1612fn format_complex(real: f64, imag: f64, suffix: char) -> String {
1614 let real = clean_float(real);
1616 let imag = clean_float(imag);
1617
1618 let real_is_zero = real.abs() < 1e-15;
1620 let imag_is_zero = imag.abs() < 1e-15;
1621
1622 if real_is_zero && imag_is_zero {
1623 return "0".to_string();
1624 }
1625
1626 if imag_is_zero {
1627 if real == real.trunc() && real.abs() < 1e15 {
1629 return format!("{}", real as i64);
1630 }
1631 return format!("{}", real);
1632 }
1633
1634 if real_is_zero {
1635 if (imag - 1.0).abs() < 1e-15 {
1637 return format!("{}", suffix);
1638 }
1639 if (imag + 1.0).abs() < 1e-15 {
1640 return format!("-{}", suffix);
1641 }
1642 if imag == imag.trunc() && imag.abs() < 1e15 {
1643 return format!("{}{}", imag as i64, suffix);
1644 }
1645 return format!("{}{}", imag, suffix);
1646 }
1647
1648 let real_str = if real == real.trunc() && real.abs() < 1e15 {
1650 format!("{}", real as i64)
1651 } else {
1652 format!("{}", real)
1653 };
1654
1655 let imag_str = if (imag - 1.0).abs() < 1e-15 {
1656 format!("+{}", suffix)
1657 } else if (imag + 1.0).abs() < 1e-15 {
1658 format!("-{}", suffix)
1659 } else if imag > 0.0 {
1660 if imag == imag.trunc() && imag.abs() < 1e15 {
1661 format!("+{}{}", imag as i64, suffix)
1662 } else {
1663 format!("+{}{}", imag, suffix)
1664 }
1665 } else if imag == imag.trunc() && imag.abs() < 1e15 {
1666 format!("{}{}", imag as i64, suffix)
1667 } else {
1668 format!("{}{}", imag, suffix)
1669 };
1670
1671 format!("{}{}", real_str, imag_str)
1672}
1673
1674fn coerce_complex_str(v: &LiteralValue) -> Result<String, ExcelError> {
1676 match v {
1677 LiteralValue::Text(s) => Ok(s.clone()),
1678 LiteralValue::Int(i) => Ok(i.to_string()),
1679 LiteralValue::Number(n) => Ok(n.to_string()),
1680 LiteralValue::Error(e) => Err(e.clone()),
1681 _ => Err(ExcelError::new_value()),
1682 }
1683}
1684
1685static ARG_COMPLEX_THREE: std::sync::LazyLock<Vec<ArgSchema>> =
1687 std::sync::LazyLock::new(|| vec![ArgSchema::any(), ArgSchema::any(), ArgSchema::any()]);
1688
1689#[derive(Debug)]
1691pub struct ComplexFn;
1692impl Function for ComplexFn {
1693 func_caps!(PURE);
1694 fn name(&self) -> &'static str {
1695 "COMPLEX"
1696 }
1697 fn min_args(&self) -> usize {
1698 2
1699 }
1700 fn variadic(&self) -> bool {
1701 true
1702 }
1703 fn arg_schema(&self) -> &'static [ArgSchema] {
1704 &ARG_COMPLEX_THREE[..]
1705 }
1706 fn eval<'a, 'b, 'c>(
1707 &self,
1708 args: &'c [ArgumentHandle<'a, 'b>],
1709 _ctx: &dyn FunctionContext<'b>,
1710 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1711 let real = match args[0].value()?.into_literal() {
1712 LiteralValue::Error(e) => {
1713 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1714 }
1715 other => coerce_num(&other)?,
1716 };
1717
1718 let imag = match args[1].value()?.into_literal() {
1719 LiteralValue::Error(e) => {
1720 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1721 }
1722 other => coerce_num(&other)?,
1723 };
1724
1725 let suffix = if args.len() > 2 {
1726 match args[2].value()?.into_literal() {
1727 LiteralValue::Error(e) => {
1728 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1729 }
1730 LiteralValue::Text(s) => {
1731 let s = s.to_lowercase();
1732 if s == "i" {
1733 'i'
1734 } else if s == "j" {
1735 'j'
1736 } else if s.is_empty() {
1737 'i' } else {
1739 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
1740 ExcelError::new_value(),
1741 )));
1742 }
1743 }
1744 LiteralValue::Empty => 'i',
1745 _ => {
1746 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
1747 ExcelError::new_value(),
1748 )));
1749 }
1750 }
1751 } else {
1752 'i'
1753 };
1754
1755 let result = format_complex(real, imag, suffix);
1756 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
1757 }
1758}
1759
1760#[derive(Debug)]
1762pub struct ImRealFn;
1763impl Function for ImRealFn {
1764 func_caps!(PURE);
1765 fn name(&self) -> &'static str {
1766 "IMREAL"
1767 }
1768 fn min_args(&self) -> usize {
1769 1
1770 }
1771 fn arg_schema(&self) -> &'static [ArgSchema] {
1772 &ARG_ANY_ONE[..]
1773 }
1774 fn eval<'a, 'b, 'c>(
1775 &self,
1776 args: &'c [ArgumentHandle<'a, 'b>],
1777 _ctx: &dyn FunctionContext<'b>,
1778 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1779 let inumber = match args[0].value()?.into_literal() {
1780 LiteralValue::Error(e) => {
1781 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1782 }
1783 other => match coerce_complex_str(&other) {
1784 Ok(s) => s,
1785 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1786 },
1787 };
1788
1789 let (real, _, _) = match parse_complex(&inumber) {
1790 Ok(c) => c,
1791 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1792 };
1793
1794 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(real)))
1795 }
1796}
1797
1798#[derive(Debug)]
1800pub struct ImaginaryFn;
1801impl Function for ImaginaryFn {
1802 func_caps!(PURE);
1803 fn name(&self) -> &'static str {
1804 "IMAGINARY"
1805 }
1806 fn min_args(&self) -> usize {
1807 1
1808 }
1809 fn arg_schema(&self) -> &'static [ArgSchema] {
1810 &ARG_ANY_ONE[..]
1811 }
1812 fn eval<'a, 'b, 'c>(
1813 &self,
1814 args: &'c [ArgumentHandle<'a, 'b>],
1815 _ctx: &dyn FunctionContext<'b>,
1816 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1817 let inumber = match args[0].value()?.into_literal() {
1818 LiteralValue::Error(e) => {
1819 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1820 }
1821 other => match coerce_complex_str(&other) {
1822 Ok(s) => s,
1823 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1824 },
1825 };
1826
1827 let (_, imag, _) = match parse_complex(&inumber) {
1828 Ok(c) => c,
1829 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1830 };
1831
1832 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(imag)))
1833 }
1834}
1835
1836#[derive(Debug)]
1838pub struct ImAbsFn;
1839impl Function for ImAbsFn {
1840 func_caps!(PURE);
1841 fn name(&self) -> &'static str {
1842 "IMABS"
1843 }
1844 fn min_args(&self) -> usize {
1845 1
1846 }
1847 fn arg_schema(&self) -> &'static [ArgSchema] {
1848 &ARG_ANY_ONE[..]
1849 }
1850 fn eval<'a, 'b, 'c>(
1851 &self,
1852 args: &'c [ArgumentHandle<'a, 'b>],
1853 _ctx: &dyn FunctionContext<'b>,
1854 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1855 let inumber = match args[0].value()?.into_literal() {
1856 LiteralValue::Error(e) => {
1857 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1858 }
1859 other => match coerce_complex_str(&other) {
1860 Ok(s) => s,
1861 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1862 },
1863 };
1864
1865 let (real, imag, _) = match parse_complex(&inumber) {
1866 Ok(c) => c,
1867 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1868 };
1869
1870 let abs = (real * real + imag * imag).sqrt();
1871 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(abs)))
1872 }
1873}
1874
1875#[derive(Debug)]
1877pub struct ImArgumentFn;
1878impl Function for ImArgumentFn {
1879 func_caps!(PURE);
1880 fn name(&self) -> &'static str {
1881 "IMARGUMENT"
1882 }
1883 fn min_args(&self) -> usize {
1884 1
1885 }
1886 fn arg_schema(&self) -> &'static [ArgSchema] {
1887 &ARG_ANY_ONE[..]
1888 }
1889 fn eval<'a, 'b, 'c>(
1890 &self,
1891 args: &'c [ArgumentHandle<'a, 'b>],
1892 _ctx: &dyn FunctionContext<'b>,
1893 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1894 let inumber = match args[0].value()?.into_literal() {
1895 LiteralValue::Error(e) => {
1896 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1897 }
1898 other => match coerce_complex_str(&other) {
1899 Ok(s) => s,
1900 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1901 },
1902 };
1903
1904 let (real, imag, _) = match parse_complex(&inumber) {
1905 Ok(c) => c,
1906 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1907 };
1908
1909 if real.abs() < 1e-15 && imag.abs() < 1e-15 {
1911 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
1912 ExcelError::new_div(),
1913 )));
1914 }
1915
1916 let arg = imag.atan2(real);
1917 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(arg)))
1918 }
1919}
1920
1921#[derive(Debug)]
1923pub struct ImConjugateFn;
1924impl Function for ImConjugateFn {
1925 func_caps!(PURE);
1926 fn name(&self) -> &'static str {
1927 "IMCONJUGATE"
1928 }
1929 fn min_args(&self) -> usize {
1930 1
1931 }
1932 fn arg_schema(&self) -> &'static [ArgSchema] {
1933 &ARG_ANY_ONE[..]
1934 }
1935 fn eval<'a, 'b, 'c>(
1936 &self,
1937 args: &'c [ArgumentHandle<'a, 'b>],
1938 _ctx: &dyn FunctionContext<'b>,
1939 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1940 let inumber = match args[0].value()?.into_literal() {
1941 LiteralValue::Error(e) => {
1942 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
1943 }
1944 other => match coerce_complex_str(&other) {
1945 Ok(s) => s,
1946 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1947 },
1948 };
1949
1950 let (real, imag, suffix) = match parse_complex(&inumber) {
1951 Ok(c) => c,
1952 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
1953 };
1954
1955 let result = format_complex(real, -imag, suffix);
1956 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
1957 }
1958}
1959
1960fn check_suffix_compatibility(s1: char, s2: char) -> Result<char, ExcelError> {
1962 if s1 == s2 {
1966 Ok(s1)
1967 } else {
1968 Ok(s1)
1971 }
1972}
1973
1974#[derive(Debug)]
1976pub struct ImSumFn;
1977impl Function for ImSumFn {
1978 func_caps!(PURE);
1979 fn name(&self) -> &'static str {
1980 "IMSUM"
1981 }
1982 fn min_args(&self) -> usize {
1983 1
1984 }
1985 fn variadic(&self) -> bool {
1986 true
1987 }
1988 fn arg_schema(&self) -> &'static [ArgSchema] {
1989 &ARG_ANY_ONE[..]
1990 }
1991 fn eval<'a, 'b, 'c>(
1992 &self,
1993 args: &'c [ArgumentHandle<'a, 'b>],
1994 _ctx: &dyn FunctionContext<'b>,
1995 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
1996 let mut sum_real = 0.0;
1997 let mut sum_imag = 0.0;
1998 let mut result_suffix = 'i';
1999 let mut first = true;
2000
2001 for arg in args {
2002 let inumber = match arg.value()?.into_literal() {
2003 LiteralValue::Error(e) => {
2004 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2005 }
2006 other => match coerce_complex_str(&other) {
2007 Ok(s) => s,
2008 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2009 },
2010 };
2011
2012 let (real, imag, suffix) = match parse_complex(&inumber) {
2013 Ok(c) => c,
2014 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2015 };
2016
2017 if first {
2018 result_suffix = suffix;
2019 first = false;
2020 } else {
2021 result_suffix = check_suffix_compatibility(result_suffix, suffix)?;
2022 }
2023
2024 sum_real += real;
2025 sum_imag += imag;
2026 }
2027
2028 let result = format_complex(sum_real, sum_imag, result_suffix);
2029 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2030 }
2031}
2032
2033#[derive(Debug)]
2035pub struct ImSubFn;
2036impl Function for ImSubFn {
2037 func_caps!(PURE);
2038 fn name(&self) -> &'static str {
2039 "IMSUB"
2040 }
2041 fn min_args(&self) -> usize {
2042 2
2043 }
2044 fn arg_schema(&self) -> &'static [ArgSchema] {
2045 &ARG_ANY_TWO[..]
2046 }
2047 fn eval<'a, 'b, 'c>(
2048 &self,
2049 args: &'c [ArgumentHandle<'a, 'b>],
2050 _ctx: &dyn FunctionContext<'b>,
2051 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2052 let inumber1 = match args[0].value()?.into_literal() {
2053 LiteralValue::Error(e) => {
2054 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2055 }
2056 other => match coerce_complex_str(&other) {
2057 Ok(s) => s,
2058 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2059 },
2060 };
2061
2062 let inumber2 = match args[1].value()?.into_literal() {
2063 LiteralValue::Error(e) => {
2064 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2065 }
2066 other => match coerce_complex_str(&other) {
2067 Ok(s) => s,
2068 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2069 },
2070 };
2071
2072 let (real1, imag1, suffix1) = match parse_complex(&inumber1) {
2073 Ok(c) => c,
2074 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2075 };
2076
2077 let (real2, imag2, suffix2) = match parse_complex(&inumber2) {
2078 Ok(c) => c,
2079 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2080 };
2081
2082 let result_suffix = check_suffix_compatibility(suffix1, suffix2)?;
2083 let result = format_complex(real1 - real2, imag1 - imag2, result_suffix);
2084 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2085 }
2086}
2087
2088#[derive(Debug)]
2090pub struct ImProductFn;
2091impl Function for ImProductFn {
2092 func_caps!(PURE);
2093 fn name(&self) -> &'static str {
2094 "IMPRODUCT"
2095 }
2096 fn min_args(&self) -> usize {
2097 1
2098 }
2099 fn variadic(&self) -> bool {
2100 true
2101 }
2102 fn arg_schema(&self) -> &'static [ArgSchema] {
2103 &ARG_ANY_ONE[..]
2104 }
2105 fn eval<'a, 'b, 'c>(
2106 &self,
2107 args: &'c [ArgumentHandle<'a, 'b>],
2108 _ctx: &dyn FunctionContext<'b>,
2109 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2110 let mut prod_real = 1.0;
2111 let mut prod_imag = 0.0;
2112 let mut result_suffix = 'i';
2113 let mut first = true;
2114
2115 for arg in args {
2116 let inumber = match arg.value()?.into_literal() {
2117 LiteralValue::Error(e) => {
2118 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2119 }
2120 other => match coerce_complex_str(&other) {
2121 Ok(s) => s,
2122 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2123 },
2124 };
2125
2126 let (real, imag, suffix) = match parse_complex(&inumber) {
2127 Ok(c) => c,
2128 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2129 };
2130
2131 if first {
2132 result_suffix = suffix;
2133 prod_real = real;
2134 prod_imag = imag;
2135 first = false;
2136 } else {
2137 result_suffix = check_suffix_compatibility(result_suffix, suffix)?;
2138 let new_real = prod_real * real - prod_imag * imag;
2140 let new_imag = prod_real * imag + prod_imag * real;
2141 prod_real = new_real;
2142 prod_imag = new_imag;
2143 }
2144 }
2145
2146 let result = format_complex(prod_real, prod_imag, result_suffix);
2147 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2148 }
2149}
2150
2151#[derive(Debug)]
2153pub struct ImDivFn;
2154impl Function for ImDivFn {
2155 func_caps!(PURE);
2156 fn name(&self) -> &'static str {
2157 "IMDIV"
2158 }
2159 fn min_args(&self) -> usize {
2160 2
2161 }
2162 fn arg_schema(&self) -> &'static [ArgSchema] {
2163 &ARG_ANY_TWO[..]
2164 }
2165 fn eval<'a, 'b, 'c>(
2166 &self,
2167 args: &'c [ArgumentHandle<'a, 'b>],
2168 _ctx: &dyn FunctionContext<'b>,
2169 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2170 let inumber1 = match args[0].value()?.into_literal() {
2171 LiteralValue::Error(e) => {
2172 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2173 }
2174 other => match coerce_complex_str(&other) {
2175 Ok(s) => s,
2176 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2177 },
2178 };
2179
2180 let inumber2 = match args[1].value()?.into_literal() {
2181 LiteralValue::Error(e) => {
2182 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2183 }
2184 other => match coerce_complex_str(&other) {
2185 Ok(s) => s,
2186 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2187 },
2188 };
2189
2190 let (a, b, suffix1) = match parse_complex(&inumber1) {
2191 Ok(c) => c,
2192 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2193 };
2194
2195 let (c, d, suffix2) = match parse_complex(&inumber2) {
2196 Ok(c) => c,
2197 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2198 };
2199
2200 let denom = c * c + d * d;
2202 if denom.abs() < 1e-15 {
2203 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
2204 ExcelError::new_div(),
2205 )));
2206 }
2207
2208 let result_suffix = check_suffix_compatibility(suffix1, suffix2)?;
2209
2210 let real = (a * c + b * d) / denom;
2212 let imag = (b * c - a * d) / denom;
2213
2214 let result = format_complex(real, imag, result_suffix);
2215 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2216 }
2217}
2218
2219#[derive(Debug)]
2222pub struct ImExpFn;
2223impl Function for ImExpFn {
2224 func_caps!(PURE);
2225 fn name(&self) -> &'static str {
2226 "IMEXP"
2227 }
2228 fn min_args(&self) -> usize {
2229 1
2230 }
2231 fn arg_schema(&self) -> &'static [ArgSchema] {
2232 &ARG_ANY_ONE[..]
2233 }
2234 fn eval<'a, 'b, 'c>(
2235 &self,
2236 args: &'c [ArgumentHandle<'a, 'b>],
2237 _ctx: &dyn FunctionContext<'b>,
2238 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2239 let inumber = match args[0].value()?.into_literal() {
2240 LiteralValue::Error(e) => {
2241 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2242 }
2243 other => match coerce_complex_str(&other) {
2244 Ok(s) => s,
2245 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2246 },
2247 };
2248
2249 let (a, b, suffix) = match parse_complex(&inumber) {
2250 Ok(c) => c,
2251 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2252 };
2253
2254 let exp_a = a.exp();
2256 let real = exp_a * b.cos();
2257 let imag = exp_a * b.sin();
2258
2259 let result = format_complex(real, imag, suffix);
2260 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2261 }
2262}
2263
2264#[derive(Debug)]
2267pub struct ImLnFn;
2268impl Function for ImLnFn {
2269 func_caps!(PURE);
2270 fn name(&self) -> &'static str {
2271 "IMLN"
2272 }
2273 fn min_args(&self) -> usize {
2274 1
2275 }
2276 fn arg_schema(&self) -> &'static [ArgSchema] {
2277 &ARG_ANY_ONE[..]
2278 }
2279 fn eval<'a, 'b, 'c>(
2280 &self,
2281 args: &'c [ArgumentHandle<'a, 'b>],
2282 _ctx: &dyn FunctionContext<'b>,
2283 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2284 let inumber = match args[0].value()?.into_literal() {
2285 LiteralValue::Error(e) => {
2286 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2287 }
2288 other => match coerce_complex_str(&other) {
2289 Ok(s) => s,
2290 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2291 },
2292 };
2293
2294 let (a, b, suffix) = match parse_complex(&inumber) {
2295 Ok(c) => c,
2296 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2297 };
2298
2299 let modulus = (a * a + b * b).sqrt();
2301 if modulus < 1e-15 {
2302 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
2303 ExcelError::new_num(),
2304 )));
2305 }
2306
2307 let real = modulus.ln();
2309 let imag = b.atan2(a);
2310
2311 let result = format_complex(real, imag, suffix);
2312 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2313 }
2314}
2315
2316#[derive(Debug)]
2319pub struct ImLog10Fn;
2320impl Function for ImLog10Fn {
2321 func_caps!(PURE);
2322 fn name(&self) -> &'static str {
2323 "IMLOG10"
2324 }
2325 fn min_args(&self) -> usize {
2326 1
2327 }
2328 fn arg_schema(&self) -> &'static [ArgSchema] {
2329 &ARG_ANY_ONE[..]
2330 }
2331 fn eval<'a, 'b, 'c>(
2332 &self,
2333 args: &'c [ArgumentHandle<'a, 'b>],
2334 _ctx: &dyn FunctionContext<'b>,
2335 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2336 let inumber = match args[0].value()?.into_literal() {
2337 LiteralValue::Error(e) => {
2338 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2339 }
2340 other => match coerce_complex_str(&other) {
2341 Ok(s) => s,
2342 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2343 },
2344 };
2345
2346 let (a, b, suffix) = match parse_complex(&inumber) {
2347 Ok(c) => c,
2348 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2349 };
2350
2351 let modulus = (a * a + b * b).sqrt();
2353 if modulus < 1e-15 {
2354 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
2355 ExcelError::new_num(),
2356 )));
2357 }
2358
2359 let ln10 = 10.0_f64.ln();
2361 let real = modulus.ln() / ln10;
2362 let imag = b.atan2(a) / ln10;
2363
2364 let result = format_complex(real, imag, suffix);
2365 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2366 }
2367}
2368
2369#[derive(Debug)]
2372pub struct ImLog2Fn;
2373impl Function for ImLog2Fn {
2374 func_caps!(PURE);
2375 fn name(&self) -> &'static str {
2376 "IMLOG2"
2377 }
2378 fn min_args(&self) -> usize {
2379 1
2380 }
2381 fn arg_schema(&self) -> &'static [ArgSchema] {
2382 &ARG_ANY_ONE[..]
2383 }
2384 fn eval<'a, 'b, 'c>(
2385 &self,
2386 args: &'c [ArgumentHandle<'a, 'b>],
2387 _ctx: &dyn FunctionContext<'b>,
2388 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2389 let inumber = match args[0].value()?.into_literal() {
2390 LiteralValue::Error(e) => {
2391 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2392 }
2393 other => match coerce_complex_str(&other) {
2394 Ok(s) => s,
2395 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2396 },
2397 };
2398
2399 let (a, b, suffix) = match parse_complex(&inumber) {
2400 Ok(c) => c,
2401 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2402 };
2403
2404 let modulus = (a * a + b * b).sqrt();
2406 if modulus < 1e-15 {
2407 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
2408 ExcelError::new_num(),
2409 )));
2410 }
2411
2412 let ln2 = 2.0_f64.ln();
2414 let real = modulus.ln() / ln2;
2415 let imag = b.atan2(a) / ln2;
2416
2417 let result = format_complex(real, imag, suffix);
2418 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2419 }
2420}
2421
2422#[derive(Debug)]
2425pub struct ImPowerFn;
2426impl Function for ImPowerFn {
2427 func_caps!(PURE);
2428 fn name(&self) -> &'static str {
2429 "IMPOWER"
2430 }
2431 fn min_args(&self) -> usize {
2432 2
2433 }
2434 fn arg_schema(&self) -> &'static [ArgSchema] {
2435 &ARG_ANY_TWO[..]
2436 }
2437 fn eval<'a, 'b, 'c>(
2438 &self,
2439 args: &'c [ArgumentHandle<'a, 'b>],
2440 _ctx: &dyn FunctionContext<'b>,
2441 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2442 let inumber = match args[0].value()?.into_literal() {
2443 LiteralValue::Error(e) => {
2444 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2445 }
2446 other => match coerce_complex_str(&other) {
2447 Ok(s) => s,
2448 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2449 },
2450 };
2451
2452 let n = match args[1].value()?.into_literal() {
2453 LiteralValue::Error(e) => {
2454 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2455 }
2456 other => coerce_num(&other)?,
2457 };
2458
2459 let (a, b, suffix) = match parse_complex(&inumber) {
2460 Ok(c) => c,
2461 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2462 };
2463
2464 let modulus = (a * a + b * b).sqrt();
2465 let theta = b.atan2(a);
2466
2467 if modulus < 1e-15 {
2469 if n > 0.0 {
2470 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(
2471 "0".to_string(),
2472 )));
2473 } else {
2474 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
2476 ExcelError::new_num(),
2477 )));
2478 }
2479 }
2480
2481 let r_n = modulus.powf(n);
2483 let n_theta = n * theta;
2484 let real = r_n * n_theta.cos();
2485 let imag = r_n * n_theta.sin();
2486
2487 let result = format_complex(real, imag, suffix);
2488 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2489 }
2490}
2491
2492#[derive(Debug)]
2495pub struct ImSqrtFn;
2496impl Function for ImSqrtFn {
2497 func_caps!(PURE);
2498 fn name(&self) -> &'static str {
2499 "IMSQRT"
2500 }
2501 fn min_args(&self) -> usize {
2502 1
2503 }
2504 fn arg_schema(&self) -> &'static [ArgSchema] {
2505 &ARG_ANY_ONE[..]
2506 }
2507 fn eval<'a, 'b, 'c>(
2508 &self,
2509 args: &'c [ArgumentHandle<'a, 'b>],
2510 _ctx: &dyn FunctionContext<'b>,
2511 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2512 let inumber = match args[0].value()?.into_literal() {
2513 LiteralValue::Error(e) => {
2514 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2515 }
2516 other => match coerce_complex_str(&other) {
2517 Ok(s) => s,
2518 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2519 },
2520 };
2521
2522 let (a, b, suffix) = match parse_complex(&inumber) {
2523 Ok(c) => c,
2524 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2525 };
2526
2527 let modulus = (a * a + b * b).sqrt();
2528 let theta = b.atan2(a);
2529
2530 let sqrt_r = modulus.sqrt();
2532 let half_theta = theta / 2.0;
2533 let real = sqrt_r * half_theta.cos();
2534 let imag = sqrt_r * half_theta.sin();
2535
2536 let result = format_complex(real, imag, suffix);
2537 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2538 }
2539}
2540
2541#[derive(Debug)]
2544pub struct ImSinFn;
2545impl Function for ImSinFn {
2546 func_caps!(PURE);
2547 fn name(&self) -> &'static str {
2548 "IMSIN"
2549 }
2550 fn min_args(&self) -> usize {
2551 1
2552 }
2553 fn arg_schema(&self) -> &'static [ArgSchema] {
2554 &ARG_ANY_ONE[..]
2555 }
2556 fn eval<'a, 'b, 'c>(
2557 &self,
2558 args: &'c [ArgumentHandle<'a, 'b>],
2559 _ctx: &dyn FunctionContext<'b>,
2560 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2561 let inumber = match args[0].value()?.into_literal() {
2562 LiteralValue::Error(e) => {
2563 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2564 }
2565 other => match coerce_complex_str(&other) {
2566 Ok(s) => s,
2567 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2568 },
2569 };
2570
2571 let (a, b, suffix) = match parse_complex(&inumber) {
2572 Ok(c) => c,
2573 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2574 };
2575
2576 let real = a.sin() * b.cosh();
2578 let imag = a.cos() * b.sinh();
2579
2580 let result = format_complex(real, imag, suffix);
2581 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2582 }
2583}
2584
2585#[derive(Debug)]
2588pub struct ImCosFn;
2589impl Function for ImCosFn {
2590 func_caps!(PURE);
2591 fn name(&self) -> &'static str {
2592 "IMCOS"
2593 }
2594 fn min_args(&self) -> usize {
2595 1
2596 }
2597 fn arg_schema(&self) -> &'static [ArgSchema] {
2598 &ARG_ANY_ONE[..]
2599 }
2600 fn eval<'a, 'b, 'c>(
2601 &self,
2602 args: &'c [ArgumentHandle<'a, 'b>],
2603 _ctx: &dyn FunctionContext<'b>,
2604 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2605 let inumber = match args[0].value()?.into_literal() {
2606 LiteralValue::Error(e) => {
2607 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2608 }
2609 other => match coerce_complex_str(&other) {
2610 Ok(s) => s,
2611 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2612 },
2613 };
2614
2615 let (a, b, suffix) = match parse_complex(&inumber) {
2616 Ok(c) => c,
2617 Err(e) => return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2618 };
2619
2620 let real = a.cos() * b.cosh();
2622 let imag = -a.sin() * b.sinh();
2623
2624 let result = format_complex(real, imag, suffix);
2625 Ok(crate::traits::CalcValue::Scalar(LiteralValue::Text(result)))
2626 }
2627}
2628
2629#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2633enum UnitCategory {
2634 Length,
2635 Mass,
2636 Temperature,
2637}
2638
2639struct UnitInfo {
2641 category: UnitCategory,
2642 to_base: f64,
2645}
2646
2647fn get_unit_info(unit: &str) -> Option<UnitInfo> {
2649 match unit {
2651 "m" => Some(UnitInfo {
2653 category: UnitCategory::Length,
2654 to_base: 1.0,
2655 }),
2656 "km" => Some(UnitInfo {
2657 category: UnitCategory::Length,
2658 to_base: 1000.0,
2659 }),
2660 "cm" => Some(UnitInfo {
2661 category: UnitCategory::Length,
2662 to_base: 0.01,
2663 }),
2664 "mm" => Some(UnitInfo {
2665 category: UnitCategory::Length,
2666 to_base: 0.001,
2667 }),
2668 "mi" => Some(UnitInfo {
2670 category: UnitCategory::Length,
2671 to_base: 1609.344,
2672 }),
2673 "ft" => Some(UnitInfo {
2674 category: UnitCategory::Length,
2675 to_base: 0.3048,
2676 }),
2677 "in" => Some(UnitInfo {
2678 category: UnitCategory::Length,
2679 to_base: 0.0254,
2680 }),
2681 "yd" => Some(UnitInfo {
2682 category: UnitCategory::Length,
2683 to_base: 0.9144,
2684 }),
2685 "Nmi" => Some(UnitInfo {
2686 category: UnitCategory::Length,
2687 to_base: 1852.0,
2688 }),
2689
2690 "g" => Some(UnitInfo {
2692 category: UnitCategory::Mass,
2693 to_base: 1.0,
2694 }),
2695 "kg" => Some(UnitInfo {
2696 category: UnitCategory::Mass,
2697 to_base: 1000.0,
2698 }),
2699 "mg" => Some(UnitInfo {
2700 category: UnitCategory::Mass,
2701 to_base: 0.001,
2702 }),
2703 "lbm" => Some(UnitInfo {
2704 category: UnitCategory::Mass,
2705 to_base: 453.59237,
2706 }),
2707 "oz" => Some(UnitInfo {
2708 category: UnitCategory::Mass,
2709 to_base: 28.349523125,
2710 }),
2711 "ozm" => Some(UnitInfo {
2712 category: UnitCategory::Mass,
2713 to_base: 28.349523125,
2714 }),
2715 "ton" => Some(UnitInfo {
2716 category: UnitCategory::Mass,
2717 to_base: 907184.74,
2718 }),
2719
2720 "C" | "cel" => Some(UnitInfo {
2722 category: UnitCategory::Temperature,
2723 to_base: 0.0, }),
2725 "F" | "fah" => Some(UnitInfo {
2726 category: UnitCategory::Temperature,
2727 to_base: 0.0, }),
2729 "K" | "kel" => Some(UnitInfo {
2730 category: UnitCategory::Temperature,
2731 to_base: 0.0, }),
2733
2734 _ => None,
2735 }
2736}
2737
2738fn normalize_temp_unit(unit: &str) -> &str {
2740 match unit {
2741 "C" | "cel" => "C",
2742 "F" | "fah" => "F",
2743 "K" | "kel" => "K",
2744 _ => unit,
2745 }
2746}
2747
2748fn convert_temperature(value: f64, from: &str, to: &str) -> f64 {
2750 let from = normalize_temp_unit(from);
2751 let to = normalize_temp_unit(to);
2752
2753 if from == to {
2754 return value;
2755 }
2756
2757 let celsius = match from {
2759 "C" => value,
2760 "F" => (value - 32.0) * 5.0 / 9.0,
2761 "K" => value - 273.15,
2762 _ => value,
2763 };
2764
2765 match to {
2767 "C" => celsius,
2768 "F" => celsius * 9.0 / 5.0 + 32.0,
2769 "K" => celsius + 273.15,
2770 _ => celsius,
2771 }
2772}
2773
2774fn convert_units(value: f64, from: &str, to: &str) -> Result<f64, ExcelError> {
2776 let from_info = get_unit_info(from).ok_or_else(ExcelError::new_na)?;
2777 let to_info = get_unit_info(to).ok_or_else(ExcelError::new_na)?;
2778
2779 if from_info.category != to_info.category {
2781 return Err(ExcelError::new_na());
2782 }
2783
2784 if from_info.category == UnitCategory::Temperature {
2786 return Ok(convert_temperature(value, from, to));
2787 }
2788
2789 let base_value = value * from_info.to_base;
2791 Ok(base_value / to_info.to_base)
2792}
2793
2794#[derive(Debug)]
2796pub struct ConvertFn;
2797impl Function for ConvertFn {
2798 func_caps!(PURE);
2799 fn name(&self) -> &'static str {
2800 "CONVERT"
2801 }
2802 fn min_args(&self) -> usize {
2803 3
2804 }
2805 fn arg_schema(&self) -> &'static [ArgSchema] {
2806 &ARG_COMPLEX_THREE[..]
2807 }
2808 fn eval<'a, 'b, 'c>(
2809 &self,
2810 args: &'c [ArgumentHandle<'a, 'b>],
2811 _ctx: &dyn FunctionContext<'b>,
2812 ) -> Result<crate::traits::CalcValue<'b>, ExcelError> {
2813 let value = match args[0].value()?.into_literal() {
2815 LiteralValue::Error(e) => {
2816 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2817 }
2818 other => coerce_num(&other)?,
2819 };
2820
2821 let from_unit = match args[1].value()?.into_literal() {
2823 LiteralValue::Error(e) => {
2824 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2825 }
2826 LiteralValue::Text(s) => s,
2827 _ => {
2828 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
2829 ExcelError::new_na(),
2830 )));
2831 }
2832 };
2833
2834 let to_unit = match args[2].value()?.into_literal() {
2836 LiteralValue::Error(e) => {
2837 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e)));
2838 }
2839 LiteralValue::Text(s) => s,
2840 _ => {
2841 return Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(
2842 ExcelError::new_na(),
2843 )));
2844 }
2845 };
2846
2847 match convert_units(value, &from_unit, &to_unit) {
2848 Ok(result) => Ok(crate::traits::CalcValue::Scalar(LiteralValue::Number(
2849 result,
2850 ))),
2851 Err(e) => Ok(crate::traits::CalcValue::Scalar(LiteralValue::Error(e))),
2852 }
2853 }
2854}
2855
2856pub fn register_builtins() {
2857 use std::sync::Arc;
2858 crate::function_registry::register_function(Arc::new(BitAndFn));
2859 crate::function_registry::register_function(Arc::new(BitOrFn));
2860 crate::function_registry::register_function(Arc::new(BitXorFn));
2861 crate::function_registry::register_function(Arc::new(BitLShiftFn));
2862 crate::function_registry::register_function(Arc::new(BitRShiftFn));
2863 crate::function_registry::register_function(Arc::new(Bin2DecFn));
2864 crate::function_registry::register_function(Arc::new(Dec2BinFn));
2865 crate::function_registry::register_function(Arc::new(Hex2DecFn));
2866 crate::function_registry::register_function(Arc::new(Dec2HexFn));
2867 crate::function_registry::register_function(Arc::new(Oct2DecFn));
2868 crate::function_registry::register_function(Arc::new(Dec2OctFn));
2869 crate::function_registry::register_function(Arc::new(Bin2HexFn));
2870 crate::function_registry::register_function(Arc::new(Hex2BinFn));
2871 crate::function_registry::register_function(Arc::new(Bin2OctFn));
2872 crate::function_registry::register_function(Arc::new(Oct2BinFn));
2873 crate::function_registry::register_function(Arc::new(Hex2OctFn));
2874 crate::function_registry::register_function(Arc::new(Oct2HexFn));
2875 crate::function_registry::register_function(Arc::new(DeltaFn));
2876 crate::function_registry::register_function(Arc::new(GestepFn));
2877 crate::function_registry::register_function(Arc::new(ErfFn));
2878 crate::function_registry::register_function(Arc::new(ErfcFn));
2879 crate::function_registry::register_function(Arc::new(ErfPreciseFn));
2880 crate::function_registry::register_function(Arc::new(ComplexFn));
2882 crate::function_registry::register_function(Arc::new(ImRealFn));
2883 crate::function_registry::register_function(Arc::new(ImaginaryFn));
2884 crate::function_registry::register_function(Arc::new(ImAbsFn));
2885 crate::function_registry::register_function(Arc::new(ImArgumentFn));
2886 crate::function_registry::register_function(Arc::new(ImConjugateFn));
2887 crate::function_registry::register_function(Arc::new(ImSumFn));
2888 crate::function_registry::register_function(Arc::new(ImSubFn));
2889 crate::function_registry::register_function(Arc::new(ImProductFn));
2890 crate::function_registry::register_function(Arc::new(ImDivFn));
2891 crate::function_registry::register_function(Arc::new(ImExpFn));
2893 crate::function_registry::register_function(Arc::new(ImLnFn));
2894 crate::function_registry::register_function(Arc::new(ImLog10Fn));
2895 crate::function_registry::register_function(Arc::new(ImLog2Fn));
2896 crate::function_registry::register_function(Arc::new(ImPowerFn));
2897 crate::function_registry::register_function(Arc::new(ImSqrtFn));
2898 crate::function_registry::register_function(Arc::new(ImSinFn));
2899 crate::function_registry::register_function(Arc::new(ImCosFn));
2900 crate::function_registry::register_function(Arc::new(ConvertFn));
2902}