1use crate::slab::{ParseSlab, CompileSlab};
30use crate::parser::{Expression, ExprPair, Value, UnaryOp::{self, EPos, ENeg, ENot, EParentheses}, BinaryOp::{self, EOR, EAND, ENE, EEQ, EGTE, ELTE, EGT, ELT, EAdd, ESub, EMul, EDiv, EMod, EExp}, StdFunc::{self, EVar, EFunc, EFuncInt, EFuncCeil, EFuncFloor, EFuncAbs, EFuncSign, EFuncLog, EFuncRound, EFuncMin, EFuncMax, EFuncE, EFuncPi, EFuncSin, EFuncCos, EFuncTan, EFuncASin, EFuncACos, EFuncATan, EFuncSinH, EFuncCosH, EFuncTanH, EFuncASinH, EFuncACosH, EFuncATanH}, PrintFunc};
31#[cfg(feature="unsafe-vars")]
32use crate::parser::StdFunc::EUnsafeVar;
33
34
35#[macro_export]
37macro_rules! bool_to_f64 {
38 ($b:expr) => {
39 if $b { 1.0 }
40 else { 0.0 }
41 };
42}
43
44
45#[derive(Debug, PartialEq, Copy, Clone)]
50pub struct InstructionI(pub usize);
51
52#[derive(Debug, PartialEq)]
54pub enum IC {
55 I(InstructionI),
56 C(f64),
57}
58
59macro_rules! instr_to_ic {
60 ($cslab:ident, $instr:ident) => {
61 match $instr {
62 IConst(c) => IC::C(c),
63 _ => IC::I($cslab.push_instr($instr)),
64 }
65 }
66}
67macro_rules! ic_to_instr {
68 ($cslab:expr, $dst:ident, $ic:ident) => {
69 match $ic {
70 IC::C(c) => {
71 $dst = IConst(*c);
72 &$dst
73 }
74 IC::I(i) => get_instr!($cslab,i),
75 }
76 }
77}
78
79#[derive(Debug, PartialEq)]
81pub enum Instruction {
82 IConst(f64),
84
85 INeg(InstructionI),
89 INot(InstructionI),
90 IInv(InstructionI),
91
92 IAdd(InstructionI, IC),
94 IMul(InstructionI, IC),
96 IMod{dividend:IC, divisor:IC},
98 IExp{base:IC, power:IC},
99
100 ILT(IC, IC),
102 ILTE(IC, IC),
103 IEQ(IC, IC),
104 INE(IC, IC),
105 IGTE(IC, IC),
106 IGT(IC, IC),
107
108 IOR(InstructionI, IC),
110 IAND(InstructionI, IC),
111
112 IVar(String),
114 #[cfg(feature="unsafe-vars")]
115 IUnsafeVar{name:String, ptr:*const f64},
116 IFunc{name:String, args:Vec<IC>},
117
118 IFuncInt(InstructionI),
119 IFuncCeil(InstructionI),
120 IFuncFloor(InstructionI),
121 IFuncAbs(InstructionI),
122 IFuncSign(InstructionI),
123 IFuncLog{base:IC, of:IC},
124 IFuncRound{modulus:IC, of:IC},
125 IFuncMin(InstructionI, IC),
126 IFuncMax(InstructionI, IC),
127
128 IFuncSin(InstructionI),
129 IFuncCos(InstructionI),
130 IFuncTan(InstructionI),
131 IFuncASin(InstructionI),
132 IFuncACos(InstructionI),
133 IFuncATan(InstructionI),
134 IFuncSinH(InstructionI),
135 IFuncCosH(InstructionI),
136 IFuncTanH(InstructionI),
137 IFuncASinH(InstructionI),
138 IFuncACosH(InstructionI),
139 IFuncATanH(InstructionI),
140
141 IPrintFunc(PrintFunc), }
143use Instruction::{IConst, INeg, INot, IInv, IAdd, IMul, IMod, IExp, ILT, ILTE, IEQ, INE, IGTE, IGT, IOR, IAND, IVar, IFunc, IFuncInt, IFuncCeil, IFuncFloor, IFuncAbs, IFuncSign, IFuncLog, IFuncRound, IFuncMin, IFuncMax, IFuncSin, IFuncCos, IFuncTan, IFuncASin, IFuncACos, IFuncATan, IFuncSinH, IFuncCosH, IFuncTanH, IFuncASinH, IFuncACosH, IFuncATanH, IPrintFunc};
144#[cfg(feature="unsafe-vars")]
145use Instruction::IUnsafeVar;
146
147impl Default for Instruction {
148 fn default() -> Self { IConst(std::f64::NAN) }
149}
150
151
152pub trait Compiler {
154 fn compile(&self, pslab:&ParseSlab, cslab:&mut CompileSlab) -> Instruction;
158}
159
160
161#[derive(Debug)]
162struct ExprSlice<'s> {
163 first: &'s Value,
164 pairs: Vec<&'s ExprPair>,
165}
166impl<'s> ExprSlice<'s> {
167 fn new(first:&Value) -> ExprSlice<'_> {
168 ExprSlice{
169 first,
170 pairs:Vec::with_capacity(8),
171 }
172 }
173 fn from_expr(expr:&Expression) -> ExprSlice<'_> {
174 let mut sl = ExprSlice::new(&expr.first);
175 for exprpairref in expr.pairs.iter() { sl.pairs.push(exprpairref) }
176 sl
177 }
178 fn split(&self, bop:BinaryOp, dst:&mut Vec<ExprSlice<'s>>) {
179 dst.push(ExprSlice::new(&self.first));
180 for exprpair in self.pairs.iter() {
181 if exprpair.0==bop {
182 dst.push(ExprSlice::new(&exprpair.1));
183 } else {
184 match dst.last_mut() {
185 Some(cur) => cur.pairs.push(exprpair),
186 None => (), }
188 }
189 }
190 }
191 fn split_multi(&self, search:&[BinaryOp], xsdst:&mut Vec<ExprSlice<'s>>, opdst:&mut Vec<&'s BinaryOp>) {
192 xsdst.push(ExprSlice::new(&self.first));
193 for exprpair in self.pairs.iter() {
194 if search.contains(&exprpair.0) {
195 xsdst.push(ExprSlice::new(&exprpair.1));
196 opdst.push(&exprpair.0);
197 } else {
198 match xsdst.last_mut() {
199 Some(cur) => cur.pairs.push(exprpair),
200 None => (), }
202 }
203 }
204 }
205}
206
207#[macro_export]
209macro_rules! f64_eq {
210 ($l:ident, $r:literal) => {
211 ($l-$r).abs() <= 8.0*std::f64::EPSILON
212 };
213 ($l:ident, $r:ident) => {
214 ($l-$r).abs() <= 8.0*std::f64::EPSILON
215 };
216 ($l:expr, $r:literal) => {
217 ($l-$r).abs() <= 8.0*std::f64::EPSILON
218 };
219 ($l:expr, $r:expr) => {
220 (($l)-($r)).abs() <= 8.0*std::f64::EPSILON
221 };
222}
223
224#[macro_export]
228macro_rules! f64_ne {
229 ($l:ident, $r:literal) => {
230 ($l-$r).abs() > 8.0*std::f64::EPSILON
231 };
232 ($l:ident, $r:ident) => {
233 ($l-$r).abs() > 8.0*std::f64::EPSILON
234 };
235 ($l:expr, $r:literal) => {
236 ($l-$r).abs() > 8.0*std::f64::EPSILON
237 };
238 ($l:expr, $r:expr) => {
239 (($l)-($r)).abs() > 8.0*std::f64::EPSILON
240 };
241}
242fn neg_wrap(instr:Instruction, cslab:&mut CompileSlab) -> Instruction {
243 if let IConst(c) = instr {
244 IConst(-c)
245 } else if let INeg(i) = instr {
246 cslab.take_instr(i)
247 } else {
248 INeg(cslab.push_instr(instr))
249 }
250}
251fn not_wrap(instr:Instruction, cslab:&mut CompileSlab) -> Instruction {
252 if let IConst(c) = instr {
253 IConst(bool_to_f64!(f64_eq!(c,0.0)))
254 } else if let INot(i) = instr {
255 cslab.take_instr(i)
256 } else {
257 INot(cslab.push_instr(instr))
258 }
259}
260fn inv_wrap(instr:Instruction, cslab:&mut CompileSlab) -> Instruction {
261 if let IConst(c) = instr {
262 IConst(1.0/c)
263 } else if let IInv(i) = instr {
264 cslab.take_instr(i)
265 } else {
266 IInv(cslab.push_instr(instr))
267 }
268}
269fn compile_mul(instrs:Vec<Instruction>, cslab:&mut CompileSlab) -> Instruction {
270 let mut out = IConst(1.0); let mut out_set = false;
271 let mut const_prod = 1.0;
272 for instr in instrs {
273 if let IConst(c) = instr {
274 const_prod *= c; } else {
276 if out_set {
277 out = IMul(cslab.push_instr(out), IC::I(cslab.push_instr(instr)));
278 } else {
279 out = instr;
280 out_set = true;
281 }
282 }
283 }
284 if f64_ne!(const_prod,1.0) {
285 if out_set {
286 out = IMul(cslab.push_instr(out), IC::C(const_prod));
287 } else {
288 out = IConst(const_prod);
289 }
290 }
291 out
292}
293fn compile_add(instrs:Vec<Instruction>, cslab:&mut CompileSlab) -> Instruction {
294 let mut out = IConst(0.0); let mut out_set = false;
295 let mut const_sum = 0.0;
296 for instr in instrs {
297 if let IConst(c) = instr {
298 const_sum += c; } else {
300 if out_set {
301 out = IAdd(cslab.push_instr(out), IC::I(cslab.push_instr(instr)));
302 } else {
303 out = instr;
304 out_set = true;
305 }
306 }
307 }
308 if f64_ne!(const_sum,0.0) {
309 if out_set {
310 out = IAdd(cslab.push_instr(out), IC::C(const_sum));
311 } else {
312 out = IConst(const_sum);
313 }
314 }
315 out
316}
317pub(crate) fn log(base:f64, n:f64) -> f64 {
318 if f64_eq!(base,2.0) { return n.log2(); }
320 if f64_eq!(base,10.0) { return n.log10(); }
321 n.log(base)
322}
323
324fn push_mul_leaves(instrs:&mut Vec<Instruction>, cslab:&mut CompileSlab, li:InstructionI, ric:IC) {
326 match ric {
328 IC::I(ri) => {
329 let instr = cslab.take_instr(ri);
330 if let IMul(rli,rric) = instr {
331 push_mul_leaves(instrs,cslab,rli,rric);
332 } else {
333 instrs.push(instr);
334 }
335 }
336 IC::C(c) => instrs.push(IConst(c)),
337 };
338
339 let instr = cslab.take_instr(li);
340 if let IMul(lli,lric) = instr {
341 push_mul_leaves(instrs,cslab,lli,lric);
342 } else {
343 instrs.push(instr);
344 }
345}
346fn push_add_leaves(instrs:&mut Vec<Instruction>, cslab:&mut CompileSlab, li:InstructionI, ric:IC) {
347 match ric {
349 IC::I(ri) => {
350 let instr = cslab.take_instr(ri);
351 if let IAdd(rli,rric) = instr {
352 push_add_leaves(instrs,cslab,rli,rric);
353 } else {
354 instrs.push(instr);
355 }
356 }
357 IC::C(c) => instrs.push(IConst(c)),
358 };
359
360 let instr = cslab.take_instr(li);
361 if let IAdd(lli,lric) = instr {
362 push_add_leaves(instrs,cslab,lli,lric);
363 } else {
364 instrs.push(instr);
365 }
366}
367
368impl Compiler for ExprSlice<'_> {
369 fn compile(&self, pslab:&ParseSlab, cslab:&mut CompileSlab) -> Instruction {
370 let mut lowest_op = match self.pairs.first() {
387 Some(p0) => p0.0,
388 None => return self.first.compile(pslab,cslab),
389 };
390 for exprpair in self.pairs.iter() {
391 if exprpair.0<lowest_op { lowest_op=exprpair.0 }
392 }
393
394 if lowest_op==EEQ || lowest_op==ENE || lowest_op==ELT || lowest_op==EGT || lowest_op==ELTE || lowest_op==EGTE {
396 let mut ops = Vec::<&BinaryOp>::with_capacity(4);
397 let mut xss = Vec::<ExprSlice>::with_capacity(ops.len()+1);
398 self.split_multi(&[EEQ, ENE, ELT, EGT, ELTE, EGTE], &mut xss, &mut ops);
399 let mut out = match xss.first() {
400 Some(xs) => xs.compile(pslab,cslab),
401 None => IConst(std::f64::NAN), };
403 for (i,op) in ops.into_iter().enumerate() {
404 let instr = match xss.get(i+1) {
405 Some(xs) => xs.compile(pslab,cslab),
406 None => IConst(std::f64::NAN), };
408 if let IConst(l) = out {
409 if let IConst(r) = instr {
410 out = match op {
411 EEQ => IConst(bool_to_f64!(f64_eq!(l,r))),
412 ENE => IConst(bool_to_f64!(f64_ne!(l,r))),
413 ELT => IConst(bool_to_f64!(l<r)),
414 EGT => IConst(bool_to_f64!(l>r)),
415 ELTE => IConst(bool_to_f64!(l<=r)),
416 EGTE => IConst(bool_to_f64!(l>=r)),
417 _ => IConst(std::f64::NAN), };
419 continue;
420 }
421 }
422 out = match op {
423 EEQ => IEQ(instr_to_ic!(cslab,out), instr_to_ic!(cslab,instr)),
424 ENE => INE(instr_to_ic!(cslab,out), instr_to_ic!(cslab,instr)),
425 ELT => ILT(instr_to_ic!(cslab,out), instr_to_ic!(cslab,instr)),
426 EGT => IGT(instr_to_ic!(cslab,out), instr_to_ic!(cslab,instr)),
427 ELTE => ILTE(instr_to_ic!(cslab,out), instr_to_ic!(cslab,instr)),
428 EGTE => IGTE(instr_to_ic!(cslab,out), instr_to_ic!(cslab,instr)),
429 _ => IConst(std::f64::NAN), };
431 }
432 return out;
433 }
434
435 match lowest_op {
436 EOR => {
437 let mut xss = Vec::<ExprSlice>::with_capacity(4);
438 self.split(EOR, &mut xss);
439 let mut out = IConst(0.0); let mut out_set = false;
440 for xs in xss.iter() {
441 let instr = xs.compile(pslab,cslab);
442 if out_set {
443 out = IOR(cslab.push_instr(out), instr_to_ic!(cslab,instr));
444 } else {
445 if let IConst(c) = instr {
446 if f64_ne!(c,0.0) { return instr; }
447 } else {
450 out = instr;
451 out_set = true;
452 }
453 }
454 }
455 out
456 }
457 EAND => {
458 let mut xss = Vec::<ExprSlice>::with_capacity(4);
459 self.split(EAND, &mut xss);
460 let mut out = IConst(1.0); let mut out_set = false;
461 for xs in xss.iter() {
462 let instr = xs.compile(pslab,cslab);
463 if let IConst(c) = instr {
464 if f64_eq!(c,0.0) { return instr; }
465 }
466 if out_set {
467 if let IConst(_) = out {
468 out = instr;
470 } else {
471 out = IAND(cslab.push_instr(out), instr_to_ic!(cslab,instr));
472 }
473 } else {
474 out = instr;
475 out_set = true;
476 }
477 }
478 out
479 }
480 EAdd => {
481 let mut xss = Vec::<ExprSlice>::with_capacity(4);
482 self.split(EAdd, &mut xss);
483 let mut instrs = Vec::<Instruction>::with_capacity(xss.len());
484 for xs in xss {
485 let instr = xs.compile(pslab,cslab);
486 if let IAdd(li,ric) = instr {
487 push_add_leaves(&mut instrs,cslab,li,ric); } else {
489 instrs.push(instr);
490 }
491 }
492 compile_add(instrs,cslab)
493 }
494 ESub => {
495 let mut xss = Vec::<ExprSlice>::with_capacity(4);
498 self.split(ESub, &mut xss);
499 let mut instrs = Vec::<Instruction>::with_capacity(xss.len());
500 for (i,xs) in xss.into_iter().enumerate() {
501 let instr = xs.compile(pslab,cslab);
502 if i==0 {
503 instrs.push(instr);
504 } else {
505 instrs.push(neg_wrap(instr,cslab));
506 }
507 }
508 compile_add(instrs,cslab)
509 }
510 EMul => {
511 let mut xss = Vec::<ExprSlice>::with_capacity(4);
512 self.split(EMul, &mut xss);
513 let mut instrs = Vec::<Instruction>::with_capacity(xss.len());
514 for xs in xss {
515 let instr = xs.compile(pslab,cslab);
516 if let IMul(li,ric) = instr {
517 push_mul_leaves(&mut instrs,cslab,li,ric); } else {
519 instrs.push(instr);
520 }
521 }
522 compile_mul(instrs,cslab)
523 }
524 EDiv => {
525 let mut xss = Vec::<ExprSlice>::with_capacity(4);
528 self.split(EDiv, &mut xss);
529 let mut instrs = Vec::<Instruction>::with_capacity(xss.len());
530 for (i,xs) in xss.into_iter().enumerate() {
531 let instr = xs.compile(pslab,cslab);
532 if i==0 {
533 instrs.push(instr);
534 } else {
535 instrs.push(inv_wrap(instr,cslab));
536 }
537 }
538 compile_mul(instrs,cslab)
539 }
540EMod => {
584 let mut xss = Vec::<ExprSlice>::with_capacity(2);
585 self.split(EMod, &mut xss);
586 let mut out = IConst(0.0); let mut out_set = false;
587 for xs in xss.iter() {
588 let instr = xs.compile(pslab,cslab);
589 if out_set {
590 if let IConst(dividend) = out {
591 if let IConst(divisor) = instr {
592 out = IConst(dividend%divisor);
593 continue;
594 }
595 }
596 out = IMod{dividend:instr_to_ic!(cslab,out), divisor:instr_to_ic!(cslab,instr)};
597 } else {
598 out = instr;
599 out_set = true;
600 }
601 }
602 out
603 }
604 EExp => { let mut xss = Vec::<ExprSlice>::with_capacity(2);
606 self.split(EExp, &mut xss);
607 let mut out = IConst(0.0); let mut out_set = false;
608 for xs in xss.into_iter().rev() {
609 let instr = xs.compile(pslab,cslab);
610 if out_set {
611 if let IConst(power) = out {
612 if let IConst(base) = instr {
613 out = IConst(base.powf(power));
614 continue;
615 }
616 }
617 out = IExp{base:instr_to_ic!(cslab,instr), power:instr_to_ic!(cslab,out)};
618 } else {
619 out = instr;
620 out_set = true;
621 }
622 }
623 out
624 }
625ENE | EEQ | EGTE | ELTE | EGT | ELT => IConst(std::f64::NAN), }
648 }
649}
650
651impl Compiler for Expression {
652 fn compile(&self, pslab:&ParseSlab, cslab:&mut CompileSlab) -> Instruction {
653 let top = ExprSlice::from_expr(&self);
654 top.compile(pslab,cslab)
655 }
656}
657
658impl Compiler for Value {
659 fn compile(&self, pslab:&ParseSlab, cslab:&mut CompileSlab) -> Instruction {
660 match self {
661 Value::EConstant(c) => IConst(*c),
662 Value::EUnaryOp(u) => u.compile(pslab,cslab),
663 Value::EStdFunc(f) => f.compile(pslab,cslab),
664 Value::EPrintFunc(pf) => IPrintFunc(pf.clone()),
665 }
666 }
667}
668
669impl Compiler for UnaryOp {
670 fn compile(&self, pslab:&ParseSlab, cslab:&mut CompileSlab) -> Instruction {
671 match self {
672 EPos(i) => get_val!(pslab,i).compile(pslab,cslab),
673 ENeg(i) => {
674 let instr = get_val!(pslab,i).compile(pslab,cslab);
675 if let IConst(c) = instr {
676 IConst(-c)
677 } else {
678 neg_wrap(instr,cslab)
679 }
680 }
681 ENot(i) => {
682 let instr = get_val!(pslab,i).compile(pslab,cslab);
683 if let IConst(c) = instr {
684 IConst(bool_to_f64!(f64_eq!(c,0.0)))
685 } else {
686 not_wrap(instr,cslab)
687 }
688 }
689 EParentheses(i) => get_expr!(pslab,i).compile(pslab,cslab),
690 }
691 }
692}
693
694impl Compiler for StdFunc {
695 fn compile(&self, pslab:&ParseSlab, cslab:&mut CompileSlab) -> Instruction {
696 match self {
697 EVar(name) => IVar(name.clone()),
698 #[cfg(feature="unsafe-vars")]
699 EUnsafeVar{name,ptr} => IUnsafeVar{name:name.clone(), ptr:*ptr},
700 EFunc{name, args:xis} => {
701 let mut args = Vec::<IC>::with_capacity(xis.len());
702 for xi in xis {
703 let instr = get_expr!(pslab,xi).compile(pslab,cslab);
704 args.push(instr_to_ic!(cslab,instr));
705 }
706 IFunc{name:name.clone(), args}
707 }
708
709 EFuncInt(i) => {
710 let instr = get_expr!(pslab,i).compile(pslab,cslab);
711 if let IConst(c) = instr {
712 IConst(c.trunc())
713 } else {
714 IFuncInt(cslab.push_instr(instr))
715 }
716 }
717 EFuncCeil(i) => {
718 let instr = get_expr!(pslab,i).compile(pslab,cslab);
719 if let IConst(c) = instr {
720 IConst(c.ceil())
721 } else {
722 IFuncCeil(cslab.push_instr(instr))
723 }
724 }
725 EFuncFloor(i) => {
726 let instr = get_expr!(pslab,i).compile(pslab,cslab);
727 if let IConst(c) = instr {
728 IConst(c.floor())
729 } else {
730 IFuncFloor(cslab.push_instr(instr))
731 }
732 }
733 EFuncAbs(i) => {
734 let instr = get_expr!(pslab,i).compile(pslab,cslab);
735 if let IConst(c) = instr {
736 IConst(c.abs())
737 } else {
738 IFuncAbs(cslab.push_instr(instr))
739 }
740 }
741 EFuncSign(i) => {
742 let instr = get_expr!(pslab,i).compile(pslab,cslab);
743 if let IConst(c) = instr {
744 IConst(c.signum())
745 } else {
746 IFuncSign(cslab.push_instr(instr))
747 }
748 }
749 EFuncLog{base:baseopt, expr:i} => {
750 let base = match baseopt {
751 Some(bi) => get_expr!(pslab,bi).compile(pslab,cslab),
752 None => IConst(10.0),
753 };
754 let instr = get_expr!(pslab,i).compile(pslab,cslab);
755 if let IConst(b) = base {
756 if let IConst(n) = instr {
757 return IConst(log(b,n));
758 }
759 }
760 IFuncLog{base:instr_to_ic!(cslab,base), of:instr_to_ic!(cslab,instr)}
761 }
762 EFuncRound{modulus:modopt, expr:i} => {
763 let modulus = match modopt {
764 Some(mi) => get_expr!(pslab,mi).compile(pslab,cslab),
765 None => IConst(1.0),
766 };
767 let instr = get_expr!(pslab,i).compile(pslab,cslab);
768 if let IConst(m) = modulus {
769 if let IConst(n) = instr {
770 return IConst( (n/m).round() * m ); }
772 }
773 IFuncRound{modulus:instr_to_ic!(cslab,modulus), of:instr_to_ic!(cslab,instr)}
774 }
775 EFuncMin{first:fi, rest:is} => {
776 let first = get_expr!(pslab,fi).compile(pslab,cslab);
777 let mut rest = Vec::<Instruction>::with_capacity(is.len());
778 for i in is { rest.push(get_expr!(pslab,i).compile(pslab,cslab)); }
779 let mut out = IConst(0.0); let mut out_set = false;
780 let mut const_min = 0.0; let mut const_min_set = false;
781 if let IConst(f) = first {
782 const_min = f;
783 const_min_set = true;
784 } else {
785 out = first;
786 out_set = true;
787 }
788 for instr in rest {
789 if let IConst(f) = instr {
790 if const_min_set {
791 if f<const_min { const_min=f; }
792 } else {
793 const_min = f;
794 const_min_set = true;
795 }
796 } else {
797 if out_set {
798 out = IFuncMin(cslab.push_instr(out), IC::I(cslab.push_instr(instr)));
799 } else {
800 out = instr;
801 out_set = true;
802 }
803 }
804 }
805 if const_min_set {
806 if out_set {
807 out = IFuncMin(cslab.push_instr(out), IC::C(const_min));
808 } else {
809 out = IConst(const_min);
810 }
812 }
813 out
815 }
816 EFuncMax{first:fi, rest:is} => {
817 let first = get_expr!(pslab,fi).compile(pslab,cslab);
818 let mut rest = Vec::<Instruction>::with_capacity(is.len());
819 for i in is { rest.push(get_expr!(pslab,i).compile(pslab,cslab)); }
820 let mut out = IConst(0.0); let mut out_set = false;
821 let mut const_max = 0.0; let mut const_max_set = false;
822 if let IConst(f) = first {
823 const_max = f;
824 const_max_set = true;
825 } else {
826 out = first;
827 out_set = true;
828 }
829 for instr in rest {
830 if let IConst(f) = instr {
831 if const_max_set {
832 if f>const_max { const_max=f; }
833 } else {
834 const_max = f;
835 const_max_set = true;
836 }
837 } else {
838 if out_set {
839 out = IFuncMax(cslab.push_instr(out), IC::I(cslab.push_instr(instr)));
840 } else {
841 out = instr;
842 out_set = true;
843 }
844 }
845 }
846 if const_max_set {
847 if out_set {
848 out = IFuncMax(cslab.push_instr(out), IC::C(const_max));
849 } else {
850 out = IConst(const_max);
851 }
853 }
854 out
856 }
857
858 EFuncE => IConst(std::f64::consts::E),
859 EFuncPi => IConst(std::f64::consts::PI),
860
861 EFuncSin(i) => {
862 let instr = get_expr!(pslab,i).compile(pslab,cslab);
863 if let IConst(c) = instr {
864 IConst(c.sin())
865 } else {
866 IFuncSin(cslab.push_instr(instr))
867 }
868 }
869 EFuncCos(i) => {
870 let instr = get_expr!(pslab,i).compile(pslab,cslab);
871 if let IConst(c) = instr {
872 IConst(c.cos())
873 } else {
874 IFuncCos(cslab.push_instr(instr))
875 }
876 }
877 EFuncTan(i) => {
878 let instr = get_expr!(pslab,i).compile(pslab,cslab);
879 if let IConst(c) = instr {
880 IConst(c.tan())
881 } else {
882 IFuncTan(cslab.push_instr(instr))
883 }
884 }
885 EFuncASin(i) => {
886 let instr = get_expr!(pslab,i).compile(pslab,cslab);
887 if let IConst(c) = instr {
888 IConst(c.asin())
889 } else {
890 IFuncASin(cslab.push_instr(instr))
891 }
892 }
893 EFuncACos(i) => {
894 let instr = get_expr!(pslab,i).compile(pslab,cslab);
895 if let IConst(c) = instr {
896 IConst(c.acos())
897 } else {
898 IFuncACos(cslab.push_instr(instr))
899 }
900 }
901 EFuncATan(i) => {
902 let instr = get_expr!(pslab,i).compile(pslab,cslab);
903 if let IConst(c) = instr {
904 IConst(c.atan())
905 } else {
906 IFuncATan(cslab.push_instr(instr))
907 }
908 }
909 EFuncSinH(i) => {
910 let instr = get_expr!(pslab,i).compile(pslab,cslab);
911 if let IConst(c) = instr {
912 IConst(c.sinh())
913 } else {
914 IFuncSinH(cslab.push_instr(instr))
915 }
916 }
917 EFuncCosH(i) => {
918 let instr = get_expr!(pslab,i).compile(pslab,cslab);
919 if let IConst(c) = instr {
920 IConst(c.cosh())
921 } else {
922 IFuncCosH(cslab.push_instr(instr))
923 }
924 }
925 EFuncTanH(i) => {
926 let instr = get_expr!(pslab,i).compile(pslab,cslab);
927 if let IConst(c) = instr {
928 IConst(c.tanh())
929 } else {
930 IFuncTanH(cslab.push_instr(instr))
931 }
932 }
933 EFuncASinH(i) => {
934 let instr = get_expr!(pslab,i).compile(pslab,cslab);
935 if let IConst(c) = instr {
936 IConst(c.asinh())
937 } else {
938 IFuncASinH(cslab.push_instr(instr))
939 }
940 }
941 EFuncACosH(i) => {
942 let instr = get_expr!(pslab,i).compile(pslab,cslab);
943 if let IConst(c) = instr {
944 IConst(c.acosh())
945 } else {
946 IFuncACosH(cslab.push_instr(instr))
947 }
948 }
949 EFuncATanH(i) => {
950 let instr = get_expr!(pslab,i).compile(pslab,cslab);
951 if let IConst(c) = instr {
952 IConst(c.atanh())
953 } else {
954 IFuncATanH(cslab.push_instr(instr))
955 }
956 }
957 }
958 }
959}
960