1use std::collections::HashMap;
13use std::fmt;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17pub enum Trit {
18 Neg,
19 Zero,
20 Pos,
21}
22
23impl Trit {
24 pub fn to_i8(self) -> i8 {
25 match self {
26 Trit::Neg => -1,
27 Trit::Zero => 0,
28 Trit::Pos => 1,
29 }
30 }
31
32 pub fn from_i8(v: i8) -> Option<Self> {
33 match v {
34 -1 => Some(Trit::Neg),
35 0 => Some(Trit::Zero),
36 1 => Some(Trit::Pos),
37 _ => None,
38 }
39 }
40}
41
42#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub enum Op {
45 Add, Multiply, Max, Min, Negate, Compose, }
52
53impl fmt::Display for Op {
54 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55 match self {
56 Op::Add => write!(f, "+"),
57 Op::Multiply => write!(f, "*"),
58 Op::Max => write!(f, "max"),
59 Op::Min => write!(f, "min"),
60 Op::Negate => write!(f, "neg"),
61 Op::Compose => write!(f, ">>"),
62 }
63 }
64}
65
66#[derive(Debug, Clone, PartialEq)]
68pub enum TernaryExpr {
69 Literal(Trit),
71 Var(String),
73 Unary(Op, Box<TernaryExpr>),
75 Binary(Op, Box<TernaryExpr>, Box<TernaryExpr>),
77 If(Box<TernaryExpr>, Box<TernaryExpr>, Box<TernaryExpr>),
79 Seq(Vec<TernaryExpr>),
81}
82
83impl fmt::Display for TernaryExpr {
84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85 match self {
86 TernaryExpr::Literal(t) => write!(f, "{}", t.to_i8()),
87 TernaryExpr::Var(name) => write!(f, "{}", name),
88 TernaryExpr::Unary(op, expr) => write!(f, "({} {})", op, expr),
89 TernaryExpr::Binary(op, l, r) => write!(f, "({} {} {})", l, op, r),
90 TernaryExpr::If(guard, then_e, else_e) => write!(f, "(if {} {} {})", guard, then_e, else_e),
91 TernaryExpr::Seq(exprs) => {
92 write!(f, "(seq")?;
93 for e in exprs {
94 write!(f, " {}", e)?;
95 }
96 write!(f, ")")
97 }
98 }
99 }
100}
101
102#[derive(Debug, Clone)]
104pub struct Production {
105 pub name: String,
106 pub alternatives: Vec<String>,
107}
108
109#[derive(Debug, Clone)]
111pub struct Grammar {
112 productions: Vec<Production>,
113 terminals: Vec<String>,
114}
115
116impl Grammar {
117 pub fn new() -> Self {
118 let productions = vec![
119 Production {
120 name: "expr".to_string(),
121 alternatives: vec![
122 "literal".to_string(),
123 "variable".to_string(),
124 "unary".to_string(),
125 "binary".to_string(),
126 "conditional".to_string(),
127 "sequence".to_string(),
128 ],
129 },
130 Production {
131 name: "literal".to_string(),
132 alternatives: vec!["NEG".to_string(), "ZERO".to_string(), "POS".to_string()],
133 },
134 Production {
135 name: "variable".to_string(),
136 alternatives: vec!["x".to_string(), "y".to_string(), "z".to_string()],
137 },
138 Production {
139 name: "unary".to_string(),
140 alternatives: vec!["NEGATE expr".to_string()],
141 },
142 Production {
143 name: "binary".to_string(),
144 alternatives: vec![
145 "expr ADD expr".to_string(),
146 "expr MUL expr".to_string(),
147 "expr MAX expr".to_string(),
148 "expr MIN expr".to_string(),
149 "expr COMP expr".to_string(),
150 ],
151 },
152 Production {
153 name: "conditional".to_string(),
154 alternatives: vec!["IF expr expr expr".to_string()],
155 },
156 Production {
157 name: "sequence".to_string(),
158 alternatives: vec!["SEQ expr_list".to_string()],
159 },
160 Production {
161 name: "expr_list".to_string(),
162 alternatives: vec!["expr".to_string(), "expr expr_list".to_string()],
163 },
164 ];
165
166 let terminals = vec![
167 "NEG".to_string(), "ZERO".to_string(), "POS".to_string(),
168 "ADD".to_string(), "MUL".to_string(), "MAX".to_string(), "MIN".to_string(),
169 "NEGATE".to_string(), "COMP".to_string(),
170 "IF".to_string(), "SEQ".to_string(),
171 "x".to_string(), "y".to_string(), "z".to_string(),
172 ];
173
174 Grammar { productions, terminals }
175 }
176
177 pub fn productions(&self) -> &[Production] {
178 &self.productions
179 }
180
181 pub fn terminals(&self) -> &[String] {
182 &self.terminals
183 }
184
185 pub fn is_terminal(&self, symbol: &str) -> bool {
186 self.terminals.iter().any(|t| t == symbol)
187 }
188
189 pub fn get_production(&self, name: &str) -> Option<&Production> {
190 self.productions.iter().find(|p| p.name == name)
191 }
192}
193
194#[derive(Debug, Clone, PartialEq)]
196pub enum Token {
197 Literal(Trit),
198 Var(String),
199 Op(Op),
200 If,
201 Seq,
202 LParen,
203 RParen,
204}
205
206pub struct Tokenizer;
208
209impl Tokenizer {
210 pub fn tokenize(input: &str) -> Result<Vec<Token>, String> {
211 let mut tokens = Vec::new();
212 let mut chars = input.chars().peekable();
213
214 while let Some(&ch) = chars.peek() {
215 match ch {
216 ' ' | '\t' | '\n' | '\r' => { chars.next(); }
217 '(' => { tokens.push(Token::LParen); chars.next(); }
218 ')' => { tokens.push(Token::RParen); chars.next(); }
219 '-' => {
220 chars.next();
221 if chars.peek() == Some(&'1') {
222 chars.next();
223 tokens.push(Token::Literal(Trit::Neg));
224 } else {
225 tokens.push(Token::Op(Op::Negate));
226 }
227 }
228 '0' => { chars.next(); tokens.push(Token::Literal(Trit::Zero)); }
229 '1' => { chars.next(); tokens.push(Token::Literal(Trit::Pos)); }
230 '+' => { chars.next(); tokens.push(Token::Op(Op::Add)); }
231 '*' => { chars.next(); tokens.push(Token::Op(Op::Multiply)); }
232 '>' => {
233 chars.next();
234 if chars.peek() == Some(&'>') {
235 chars.next();
236 tokens.push(Token::Op(Op::Compose));
237 }
238 }
239 _ if ch.is_alphabetic() => {
240 let mut word = String::new();
241 while let Some(&c) = chars.peek() {
242 if c.is_alphanumeric() || c == '_' {
243 word.push(c);
244 chars.next();
245 } else {
246 break;
247 }
248 }
249 match word.as_str() {
250 "neg" | "NEG" => tokens.push(Token::Op(Op::Negate)),
251 "max" | "MAX" => tokens.push(Token::Op(Op::Max)),
252 "min" | "MIN" => tokens.push(Token::Op(Op::Min)),
253 "if" | "IF" => tokens.push(Token::If),
254 "seq" | "SEQ" => tokens.push(Token::Seq),
255 _ => tokens.push(Token::Var(word)),
256 }
257 }
258 _ => return Err(format!("Unexpected character: {}", ch)),
259 }
260 }
261 Ok(tokens)
262 }
263}
264
265pub struct Parser {
267 pos: usize,
268 tokens: Vec<Token>,
269}
270
271impl Parser {
272 pub fn new(tokens: Vec<Token>) -> Self {
273 Parser { pos: 0, tokens }
274 }
275
276 pub fn parse(input: &str) -> Result<TernaryExpr, String> {
277 let tokens = Tokenizer::tokenize(input)?;
278 let mut parser = Parser::new(tokens);
279 let expr = parser.parse_expr()?;
280 if parser.pos < parser.tokens.len() {
281 return Err("Unexpected tokens after expression".to_string());
282 }
283 Ok(expr)
284 }
285
286 fn peek(&self) -> Option<&Token> {
287 self.tokens.get(self.pos)
288 }
289
290 fn advance(&mut self) -> Option<Token> {
291 if self.pos < self.tokens.len() {
292 let tok = self.tokens[self.pos].clone();
293 self.pos += 1;
294 Some(tok)
295 } else {
296 None
297 }
298 }
299
300 fn parse_expr(&mut self) -> Result<TernaryExpr, String> {
301 if self.peek() == Some(&Token::LParen) {
303 self.advance(); let expr = self.parse_inner()?;
305 if self.peek() == Some(&Token::RParen) {
306 self.advance(); }
308 return Ok(expr);
309 }
310
311 self.parse_atom()
313 }
314
315 fn parse_inner(&mut self) -> Result<TernaryExpr, String> {
316 if self.peek() == Some(&Token::If) {
318 self.advance();
319 let guard = self.parse_expr()?;
320 let then_expr = self.parse_expr()?;
321 let else_expr = self.parse_expr()?;
322 return Ok(TernaryExpr::If(
323 Box::new(guard),
324 Box::new(then_expr),
325 Box::new(else_expr),
326 ));
327 }
328
329 if self.peek() == Some(&Token::Seq) {
331 self.advance();
332 let mut exprs = Vec::new();
333 while self.peek().is_some() && self.peek() != Some(&Token::RParen) {
334 exprs.push(self.parse_expr()?);
335 }
336 return Ok(TernaryExpr::Seq(exprs));
337 }
338
339 let left = self.parse_expr()?;
341
342 if let Some(Token::Op(op)) = self.peek() {
344 if matches!(op, Op::Add | Op::Multiply | Op::Max | Op::Min | Op::Compose) {
345 let op = *op;
346 self.advance();
347 let right = self.parse_expr()?;
348 return Ok(TernaryExpr::Binary(op, Box::new(left), Box::new(right)));
349 }
350 }
351
352 Ok(left)
353 }
354
355 fn parse_atom(&mut self) -> Result<TernaryExpr, String> {
356 match self.advance() {
357 Some(Token::Literal(t)) => Ok(TernaryExpr::Literal(t)),
358 Some(Token::Var(name)) => Ok(TernaryExpr::Var(name)),
359 Some(Token::Op(Op::Negate)) => {
360 let expr = self.parse_expr()?;
361 Ok(TernaryExpr::Unary(Op::Negate, Box::new(expr)))
362 }
363 Some(Token::LParen) => {
364 let expr = self.parse_inner()?;
365 if self.peek() == Some(&Token::RParen) {
366 self.advance();
367 }
368 Ok(expr)
369 }
370 other => Err(format!("Unexpected token: {:?}", other)),
371 }
372 }
373}
374
375pub struct Generator {
377 max_depth: usize,
378 counter: usize,
379}
380
381impl Generator {
382 pub fn new(max_depth: usize) -> Self {
383 Generator { max_depth, counter: 0 }
384 }
385
386 pub fn generate(&mut self) -> TernaryExpr {
388 self.gen_expr(self.max_depth)
389 }
390
391 fn gen_expr(&mut self, depth: usize) -> TernaryExpr {
392 if depth == 0 {
393 return self.gen_literal();
394 }
395
396 self.counter = self.counter.wrapping_add(1);
397 let choice = self.counter % 4;
398
399 match choice {
400 0 => self.gen_literal(),
401 1 => self.gen_var(),
402 2 => self.gen_binary(depth - 1),
403 3 => self.gen_unary(depth - 1),
404 _ => self.gen_literal(),
405 }
406 }
407
408 fn gen_literal(&mut self) -> TernaryExpr {
409 self.counter = self.counter.wrapping_add(1);
410 let trit = match self.counter % 3 {
411 0 => Trit::Neg,
412 1 => Trit::Zero,
413 _ => Trit::Pos,
414 };
415 TernaryExpr::Literal(trit)
416 }
417
418 fn gen_var(&mut self) -> TernaryExpr {
419 self.counter = self.counter.wrapping_add(1);
420 let name = match self.counter % 3 {
421 0 => "x".to_string(),
422 1 => "y".to_string(),
423 _ => "z".to_string(),
424 };
425 TernaryExpr::Var(name)
426 }
427
428 fn gen_binary(&mut self, depth: usize) -> TernaryExpr {
429 self.counter = self.counter.wrapping_add(1);
430 let op = match self.counter % 5 {
431 0 => Op::Add,
432 1 => Op::Multiply,
433 2 => Op::Max,
434 3 => Op::Min,
435 _ => Op::Compose,
436 };
437 let left = self.gen_expr(depth);
438 let right = self.gen_expr(depth);
439 TernaryExpr::Binary(op, Box::new(left), Box::new(right))
440 }
441
442 fn gen_unary(&mut self, depth: usize) -> TernaryExpr {
443 let expr = self.gen_expr(depth);
444 TernaryExpr::Unary(Op::Negate, Box::new(expr))
445 }
446
447 pub fn generate_if(&mut self) -> TernaryExpr {
449 let guard = self.gen_expr(self.max_depth.saturating_sub(1));
450 let then_expr = self.gen_literal();
451 let else_expr = self.gen_literal();
452 TernaryExpr::If(Box::new(guard), Box::new(then_expr), Box::new(else_expr))
453 }
454
455 pub fn generate_seq(&mut self, len: usize) -> TernaryExpr {
457 let exprs: Vec<TernaryExpr> = (0..len).map(|_| self.gen_expr(self.max_depth.saturating_sub(1))).collect();
458 TernaryExpr::Seq(exprs)
459 }
460}
461
462pub struct Evaluator;
464
465impl Evaluator {
466 pub fn eval(expr: &TernaryExpr, vars: &HashMap<String, Trit>) -> Result<Trit, String> {
468 match expr {
469 TernaryExpr::Literal(t) => Ok(*t),
470 TernaryExpr::Var(name) => {
471 vars.get(name).copied().ok_or_else(|| format!("Undefined variable: {}", name))
472 }
473 TernaryExpr::Unary(Op::Negate, inner) => {
474 let v = Self::eval(inner, vars)?.to_i8();
475 Trit::from_i8(-v).ok_or("Negation failed".to_string())
476 }
477 TernaryExpr::Unary(_, inner) => Self::eval(inner, vars),
478 TernaryExpr::Binary(op, left, right) => {
479 let lv = Self::eval(left, vars)?.to_i8();
480 let rv = Self::eval(right, vars)?.to_i8();
481 let result = match op {
482 Op::Add => (lv + rv).clamp(-1, 1),
483 Op::Multiply => (lv * rv).clamp(-1, 1),
484 Op::Max => lv.max(rv),
485 Op::Min => lv.min(rv),
486 Op::Compose => rv, _ => 0,
488 };
489 Ok(Trit::from_i8(result).unwrap_or(Trit::Zero))
490 }
491 TernaryExpr::If(guard, then_expr, else_expr) => {
492 let g = Self::eval(guard, vars)?;
493 if g == Trit::Pos {
494 Self::eval(then_expr, vars)
495 } else {
496 Self::eval(else_expr, vars)
497 }
498 }
499 TernaryExpr::Seq(exprs) => {
500 let mut last = Trit::Zero;
501 for e in exprs {
502 last = Self::eval(e, vars)?;
503 }
504 Ok(last)
505 }
506 }
507 }
508
509 pub fn simplify(expr: &TernaryExpr) -> TernaryExpr {
511 match expr {
512 TernaryExpr::Literal(t) => TernaryExpr::Literal(*t),
513 TernaryExpr::Var(name) => TernaryExpr::Var(name.clone()),
514 TernaryExpr::Unary(op, inner) => {
515 let simplified = Self::simplify(inner);
516 if let TernaryExpr::Literal(t) = simplified {
517 let v = t.to_i8();
519 if *op == Op::Negate {
520 TernaryExpr::Literal(Trit::from_i8(-v).unwrap_or(Trit::Zero))
521 } else {
522 TernaryExpr::Literal(t)
523 }
524 } else {
525 TernaryExpr::Unary(*op, Box::new(simplified))
526 }
527 }
528 TernaryExpr::Binary(op, left, right) => {
529 let sl = Self::simplify(left);
530 let sr = Self::simplify(right);
531 if let (TernaryExpr::Literal(l), TernaryExpr::Literal(r)) = (&sl, &sr) {
532 let lv = l.to_i8();
533 let rv = r.to_i8();
534 let result = match op {
535 Op::Add => (lv + rv).clamp(-1, 1),
536 Op::Multiply => (lv * rv).clamp(-1, 1),
537 Op::Max => lv.max(rv),
538 Op::Min => lv.min(rv),
539 Op::Compose => rv,
540 _ => 0,
541 };
542 TernaryExpr::Literal(Trit::from_i8(result).unwrap_or(Trit::Zero))
543 } else {
544 TernaryExpr::Binary(*op, Box::new(sl), Box::new(sr))
545 }
546 }
547 TernaryExpr::If(guard, then_expr, else_expr) => {
548 let sg = Self::simplify(guard);
549 if let TernaryExpr::Literal(t) = sg {
550 if t == Trit::Pos {
551 Self::simplify(then_expr)
552 } else {
553 Self::simplify(else_expr)
554 }
555 } else {
556 TernaryExpr::If(
557 Box::new(sg),
558 Box::new(Self::simplify(then_expr)),
559 Box::new(Self::simplify(else_expr)),
560 )
561 }
562 }
563 TernaryExpr::Seq(exprs) => {
564 let simplified: Vec<TernaryExpr> = exprs.iter().map(Self::simplify).collect();
565 TernaryExpr::Seq(simplified)
566 }
567 }
568 }
569}
570
571#[cfg(test)]
572mod tests {
573 use super::*;
574
575 #[test]
576 fn test_trit_values() {
577 assert_eq!(Trit::Neg.to_i8(), -1);
578 assert_eq!(Trit::Zero.to_i8(), 0);
579 assert_eq!(Trit::Pos.to_i8(), 1);
580 }
581
582 #[test]
583 fn test_expr_display_literal() {
584 let expr = TernaryExpr::Literal(Trit::Pos);
585 assert_eq!(format!("{}", expr), "1");
586 }
587
588 #[test]
589 fn test_expr_display_binary() {
590 let expr = TernaryExpr::Binary(
591 Op::Add,
592 Box::new(TernaryExpr::Literal(Trit::Pos)),
593 Box::new(TernaryExpr::Literal(Trit::Neg)),
594 );
595 assert_eq!(format!("{}", expr), "(1 + -1)");
596 }
597
598 #[test]
599 fn test_expr_display_unary() {
600 let expr = TernaryExpr::Unary(Op::Negate, Box::new(TernaryExpr::Literal(Trit::Pos)));
601 assert_eq!(format!("{}", expr), "(neg 1)");
602 }
603
604 #[test]
605 fn test_expr_display_var() {
606 let expr = TernaryExpr::Var("x".to_string());
607 assert_eq!(format!("{}", expr), "x");
608 }
609
610 #[test]
611 fn test_grammar_new() {
612 let g = Grammar::new();
613 assert!(!g.productions().is_empty());
614 assert!(!g.terminals().is_empty());
615 }
616
617 #[test]
618 fn test_grammar_is_terminal() {
619 let g = Grammar::new();
620 assert!(g.is_terminal("NEG"));
621 assert!(g.is_terminal("ADD"));
622 assert!(!g.is_terminal("expr"));
623 }
624
625 #[test]
626 fn test_grammar_get_production() {
627 let g = Grammar::new();
628 let prod = g.get_production("expr").unwrap();
629 assert_eq!(prod.name, "expr");
630 assert!(prod.alternatives.len() > 1);
631 }
632
633 #[test]
634 fn test_tokenizer_literals() {
635 let tokens = Tokenizer::tokenize("-1 0 1").unwrap();
636 assert_eq!(tokens.len(), 3);
637 assert_eq!(tokens[0], Token::Literal(Trit::Neg));
638 assert_eq!(tokens[1], Token::Literal(Trit::Zero));
639 assert_eq!(tokens[2], Token::Literal(Trit::Pos));
640 }
641
642 #[test]
643 fn test_tokenizer_operators() {
644 let tokens = Tokenizer::tokenize("+ * >>").unwrap();
645 assert_eq!(tokens.len(), 3);
646 assert_eq!(tokens[0], Token::Op(Op::Add));
647 assert_eq!(tokens[1], Token::Op(Op::Multiply));
648 assert_eq!(tokens[2], Token::Op(Op::Compose));
649 }
650
651 #[test]
652 fn test_tokenizer_keywords() {
653 let tokens = Tokenizer::tokenize("neg max min if seq").unwrap();
654 assert_eq!(tokens.len(), 5);
655 assert_eq!(tokens[0], Token::Op(Op::Negate));
656 assert_eq!(tokens[1], Token::Op(Op::Max));
657 assert_eq!(tokens[3], Token::If);
658 assert_eq!(tokens[4], Token::Seq);
659 }
660
661 #[test]
662 fn test_tokenizer_vars() {
663 let tokens = Tokenizer::tokenize("x y z").unwrap();
664 assert_eq!(tokens.len(), 3);
665 assert_eq!(tokens[0], Token::Var("x".to_string()));
666 }
667
668 #[test]
669 fn test_parser_literal() {
670 let expr = Parser::parse("1").unwrap();
671 assert_eq!(expr, TernaryExpr::Literal(Trit::Pos));
672 }
673
674 #[test]
675 fn test_parser_binary() {
676 let expr = Parser::parse("(1 + -1)").unwrap();
677 assert_eq!(expr, TernaryExpr::Binary(
678 Op::Add,
679 Box::new(TernaryExpr::Literal(Trit::Pos)),
680 Box::new(TernaryExpr::Literal(Trit::Neg)),
681 ));
682 }
683
684 #[test]
685 fn test_parser_unary() {
686 let expr = Parser::parse("neg 1").unwrap();
687 assert_eq!(expr, TernaryExpr::Unary(Op::Negate, Box::new(TernaryExpr::Literal(Trit::Pos))));
688 }
689
690 #[test]
691 fn test_parser_nested() {
692 let expr = Parser::parse("((1 + -1) * 0)").unwrap();
693 assert!(matches!(expr, TernaryExpr::Binary(Op::Multiply, _, _)));
694 }
695
696 #[test]
697 fn test_evaluator_literal() {
698 let expr = TernaryExpr::Literal(Trit::Pos);
699 let result = Evaluator::eval(&expr, &HashMap::new()).unwrap();
700 assert_eq!(result, Trit::Pos);
701 }
702
703 #[test]
704 fn test_evaluator_var() {
705 let expr = TernaryExpr::Var("x".to_string());
706 let mut vars = HashMap::new();
707 vars.insert("x".to_string(), Trit::Neg);
708 let result = Evaluator::eval(&expr, &vars).unwrap();
709 assert_eq!(result, Trit::Neg);
710 }
711
712 #[test]
713 fn test_evaluator_add() {
714 let expr = TernaryExpr::Binary(Op::Add, Box::new(TernaryExpr::Literal(Trit::Pos)), Box::new(TernaryExpr::Literal(Trit::Neg)));
715 let result = Evaluator::eval(&expr, &HashMap::new()).unwrap();
716 assert_eq!(result, Trit::Zero);
717 }
718
719 #[test]
720 fn test_evaluator_multiply() {
721 let expr = TernaryExpr::Binary(Op::Multiply, Box::new(TernaryExpr::Literal(Trit::Pos)), Box::new(TernaryExpr::Literal(Trit::Pos)));
722 let result = Evaluator::eval(&expr, &HashMap::new()).unwrap();
723 assert_eq!(result, Trit::Pos);
724 }
725
726 #[test]
727 fn test_evaluator_negate() {
728 let expr = TernaryExpr::Unary(Op::Negate, Box::new(TernaryExpr::Literal(Trit::Pos)));
729 let result = Evaluator::eval(&expr, &HashMap::new()).unwrap();
730 assert_eq!(result, Trit::Neg);
731 }
732
733 #[test]
734 fn test_evaluator_if() {
735 let expr = TernaryExpr::If(
736 Box::new(TernaryExpr::Literal(Trit::Pos)),
737 Box::new(TernaryExpr::Literal(Trit::Pos)),
738 Box::new(TernaryExpr::Literal(Trit::Neg)),
739 );
740 let result = Evaluator::eval(&expr, &HashMap::new()).unwrap();
741 assert_eq!(result, Trit::Pos);
742 }
743
744 #[test]
745 fn test_simplify_constants() {
746 let expr = TernaryExpr::Binary(Op::Add, Box::new(TernaryExpr::Literal(Trit::Pos)), Box::new(TernaryExpr::Literal(Trit::Neg)));
747 let simplified = Evaluator::simplify(&expr);
748 assert_eq!(simplified, TernaryExpr::Literal(Trit::Zero));
749 }
750}