Skip to content

Commit dc0dc3b

Browse files
committed
Merge branch 'feature/lex-instruction' into develop
2 parents b38cce7 + ca69ffb commit dc0dc3b

File tree

9 files changed

+224
-58
lines changed

9 files changed

+224
-58
lines changed

rust_project/loda-rust-core/src/execute/node_calc.rs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,32 +39,33 @@ impl NodeCalc {
3939

4040
fn calc_with_semantics<S: Semantics>(&self, target: &BigInt, source: &BigInt) -> Result<BigInt, EvalError> {
4141
match self.instruction_id {
42-
InstructionId::Move => Ok(source.clone()),
43-
InstructionId::Add => S::add(target, source),
44-
InstructionId::Subtract => S::subtract(target, source),
45-
InstructionId::Truncate => S::truncate(target, source),
46-
InstructionId::Multiply => S::multiply(target, source),
47-
InstructionId::Divide => S::divide(target, source),
48-
InstructionId::DivideIf => S::divide_if(target, source),
49-
InstructionId::DivideIfRepeat => S::divide_if_repeat(target, source),
50-
InstructionId::Modulo => S::modulo(target, source),
51-
InstructionId::Power => S::power(target, source),
52-
InstructionId::GCD => S::gcd(target, source),
53-
InstructionId::Binomial => S::binomial(target, source),
54-
InstructionId::Compare => S::compare(target, source),
55-
InstructionId::Min => S::min(target, source),
56-
InstructionId::Max => S::max(target, source),
57-
InstructionId::Logarithm => S::logarithm(target, source),
58-
InstructionId::NthRoot => S::nthroot(target, source),
59-
InstructionId::DigitSum => S::digitsum(target, source),
60-
InstructionId::DigitalRoot => S::digitalroot(target, source),
61-
InstructionId::Equal => S::equal(target, source),
62-
InstructionId::NotEqual => S::notequal(target, source),
63-
InstructionId::LessOrEqual => S::lessorequal(target, source),
64-
InstructionId::GreaterOrEqual => S::greaterorequal(target, source),
65-
InstructionId::BitwiseAnd => S::bitwiseand(target, source),
66-
InstructionId::BitwiseOr => S::bitwiseor(target, source),
67-
InstructionId::BitwiseXor => S::bitwisexor(target, source),
42+
InstructionId::Move => Ok(source.clone()),
43+
InstructionId::Add => S::add(target, source),
44+
InstructionId::Subtract => S::subtract(target, source),
45+
InstructionId::Truncate => S::truncate(target, source),
46+
InstructionId::Multiply => S::multiply(target, source),
47+
InstructionId::Divide => S::divide(target, source),
48+
InstructionId::DivideIf => S::divide_if(target, source),
49+
InstructionId::DivideIfRepeat => S::divide_if_repeat(target, source),
50+
InstructionId::Modulo => S::modulo(target, source),
51+
InstructionId::Power => S::power(target, source),
52+
InstructionId::GCD => S::gcd(target, source),
53+
InstructionId::Binomial => S::binomial(target, source),
54+
InstructionId::Compare => S::compare(target, source),
55+
InstructionId::Min => S::min(target, source),
56+
InstructionId::Max => S::max(target, source),
57+
InstructionId::Logarithm => S::logarithm(target, source),
58+
InstructionId::NthRoot => S::nthroot(target, source),
59+
InstructionId::DigitSum => S::digitsum(target, source),
60+
InstructionId::DigitalRoot => S::digitalroot(target, source),
61+
InstructionId::Equal => S::equal(target, source),
62+
InstructionId::NotEqual => S::notequal(target, source),
63+
InstructionId::LessOrEqual => S::lessorequal(target, source),
64+
InstructionId::GreaterOrEqual => S::greaterorequal(target, source),
65+
InstructionId::BitwiseAnd => S::bitwiseand(target, source),
66+
InstructionId::BitwiseOr => S::bitwiseor(target, source),
67+
InstructionId::BitwiseXor => S::bitwisexor(target, source),
68+
InstructionId::LargestExponent => S::largestexponent(target, source),
6869
_ => {
6970
error!("unsupported instruction: {:?}", self.instruction_id);
7071
return Err(EvalError::UnsupportedInstruction);

rust_project/loda-rust-core/src/execute/semantic_simple.rs

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ pub trait SemanticSimpleConfig {
5454
return Err(SemanticSimpleError::InputOutOfRange);
5555
}
5656
}
57-
let z: BigInt = x - y;
57+
let z: BigInt = x - y.clone();
5858
if let Some(value_max_bits) = self.value_max_bits() {
5959
if z.bits() >= value_max_bits {
6060
return Err(SemanticSimpleError::OutputOutOfRange);
@@ -376,6 +376,30 @@ pub trait SemanticSimpleConfig {
376376
Ok(result)
377377
}
378378

379+
fn compute_largestexponent(&self, x: &BigInt, y: &BigInt) -> Result<BigInt, SemanticSimpleError> {
380+
if let Some(value_max_bits) = self.value_max_bits() {
381+
if x.bits() >= value_max_bits || y.bits() >= value_max_bits {
382+
return Err(SemanticSimpleError::InputOutOfRange);
383+
}
384+
}
385+
if *y == BigInt::zero() || *y == BigInt::one() {
386+
return Ok(BigInt::zero());
387+
}
388+
389+
let mut xx: BigInt = x.abs();
390+
let yy: BigInt = y.abs();
391+
let mut r: BigInt = BigInt::zero();
392+
loop {
393+
let aaa: BigInt = self.compute_divide_if(&xx, &yy)?;
394+
if aaa == xx {
395+
break;
396+
}
397+
xx = aaa;
398+
r += BigInt::one();
399+
}
400+
Ok(r)
401+
}
402+
379403
fn compute_equal(&self, x: &BigInt, y: &BigInt) -> Result<BigInt, SemanticSimpleError> {
380404
if let Some(value_max_bits) = self.value_max_bits() {
381405
if x.bits() >= value_max_bits || y.bits() >= value_max_bits {
@@ -529,6 +553,7 @@ mod tests {
529553
BitwiseAnd,
530554
BitwiseOr,
531555
BitwiseXor,
556+
LargestExponent,
532557
}
533558

534559
fn compute(config: &dyn SemanticSimpleConfig, mode: ComputeMode, left: i64, right: i64) -> String {
@@ -568,6 +593,7 @@ mod tests {
568593
ComputeMode::BitwiseAnd => config.compute_bitwiseand(&x, &y),
569594
ComputeMode::BitwiseOr => config.compute_bitwiseor(&x, &y),
570595
ComputeMode::BitwiseXor => config.compute_bitwisexor(&x, &y),
596+
ComputeMode::LargestExponent => config.compute_largestexponent(&x, &y),
571597
};
572598
match result {
573599
Ok(value) => return value.to_string(),
@@ -1342,4 +1368,116 @@ mod tests {
13421368
assert_eq!(compute_bitwisexor("-9223372036854775807", "-9223372036854775808"), "18446744073709551615");
13431369
assert_eq!(compute_bitwisexor("3148244321913096809130", "1574122160956548404565"), "4722366482869645213695");
13441370
}
1371+
1372+
fn compute_largestexponent(left: i64, right: i64) -> String {
1373+
let config = SemanticSimpleConfigLimited::new(32);
1374+
compute(&config, ComputeMode::LargestExponent, left, right)
1375+
}
1376+
1377+
#[test]
1378+
fn test_230000_largestexponent() {
1379+
assert_eq!(compute_largestexponent(-4, -5), "0");
1380+
assert_eq!(compute_largestexponent(-4, -4), "1");
1381+
assert_eq!(compute_largestexponent(-4, -3), "0");
1382+
assert_eq!(compute_largestexponent(-4, -2), "2");
1383+
assert_eq!(compute_largestexponent(-4, -1), "0");
1384+
assert_eq!(compute_largestexponent(-4, 0), "0");
1385+
assert_eq!(compute_largestexponent(-4, 1), "0");
1386+
assert_eq!(compute_largestexponent(-4, 2), "2");
1387+
assert_eq!(compute_largestexponent(-4, 3), "0");
1388+
assert_eq!(compute_largestexponent(-4, 4), "1");
1389+
assert_eq!(compute_largestexponent(-4, 5), "0");
1390+
assert_eq!(compute_largestexponent(-4, 6), "0");
1391+
assert_eq!(compute_largestexponent(-4, 7), "0");
1392+
assert_eq!(compute_largestexponent(-4, 8), "0");
1393+
assert_eq!(compute_largestexponent(0, -2), "0");
1394+
assert_eq!(compute_largestexponent(0, -1), "0");
1395+
assert_eq!(compute_largestexponent(0, 0), "0");
1396+
assert_eq!(compute_largestexponent(0, 1), "0");
1397+
assert_eq!(compute_largestexponent(0, 2), "0");
1398+
assert_eq!(compute_largestexponent(1, -1), "0");
1399+
assert_eq!(compute_largestexponent(1, -1), "0");
1400+
assert_eq!(compute_largestexponent(1, 0), "0");
1401+
assert_eq!(compute_largestexponent(1, 1), "0");
1402+
assert_eq!(compute_largestexponent(1, 2), "0");
1403+
assert_eq!(compute_largestexponent(2, -3), "0");
1404+
assert_eq!(compute_largestexponent(2, -2), "1");
1405+
assert_eq!(compute_largestexponent(2, -1), "0");
1406+
assert_eq!(compute_largestexponent(2, 0), "0");
1407+
assert_eq!(compute_largestexponent(2, 1), "0");
1408+
assert_eq!(compute_largestexponent(2, 2), "1");
1409+
assert_eq!(compute_largestexponent(2, 3), "0");
1410+
assert_eq!(compute_largestexponent(2, 4), "0");
1411+
assert_eq!(compute_largestexponent(4, -5), "0");
1412+
assert_eq!(compute_largestexponent(4, -4), "1");
1413+
assert_eq!(compute_largestexponent(4, -3), "0");
1414+
assert_eq!(compute_largestexponent(4, -2), "2");
1415+
assert_eq!(compute_largestexponent(4, -1), "0");
1416+
assert_eq!(compute_largestexponent(4, 0), "0");
1417+
assert_eq!(compute_largestexponent(4, 1), "0");
1418+
assert_eq!(compute_largestexponent(4, 2), "2");
1419+
assert_eq!(compute_largestexponent(4, 3), "0");
1420+
assert_eq!(compute_largestexponent(4, 4), "1");
1421+
assert_eq!(compute_largestexponent(4, 5), "0");
1422+
assert_eq!(compute_largestexponent(9, 1), "0");
1423+
assert_eq!(compute_largestexponent(9, 2), "0");
1424+
assert_eq!(compute_largestexponent(9, 3), "2");
1425+
assert_eq!(compute_largestexponent(9, 4), "0");
1426+
assert_eq!(compute_largestexponent(9, 5), "0");
1427+
assert_eq!(compute_largestexponent(9, 9), "1");
1428+
assert_eq!(compute_largestexponent(9, 10), "0");
1429+
assert_eq!(compute_largestexponent(16, 2), "4");
1430+
assert_eq!(compute_largestexponent(16, 4), "2");
1431+
assert_eq!(compute_largestexponent(36, 2), "2");
1432+
assert_eq!(compute_largestexponent(36, 3), "2");
1433+
assert_eq!(compute_largestexponent(36, 4), "1");
1434+
assert_eq!(compute_largestexponent(36, 5), "0");
1435+
assert_eq!(compute_largestexponent(36, 6), "2");
1436+
assert_eq!(compute_largestexponent(36, 7), "0");
1437+
}
1438+
1439+
#[test]
1440+
fn test_230000_largestexponent_big_values() {
1441+
assert_eq!(compute_largestexponent(0x7fffffff, 0x7fffffff), "1");
1442+
assert_eq!(compute_largestexponent(0x7fffffff, -0x7fffffff), "1");
1443+
assert_eq!(compute_largestexponent(-0x7fffffff, 0x7fffffff), "1");
1444+
assert_eq!(compute_largestexponent(-0x7fffffff, -0x7fffffff), "1");
1445+
assert_eq!(compute_largestexponent(0x7fffffff, 0), "0");
1446+
assert_eq!(compute_largestexponent(-0x7fffffff, 0), "0");
1447+
assert_eq!(compute_largestexponent(0x7fffffff, 1), "0");
1448+
assert_eq!(compute_largestexponent(-0x7fffffff, 1), "0");
1449+
assert_eq!(compute_largestexponent(0x7fffffff, 2), "0");
1450+
assert_eq!(compute_largestexponent(-0x7fffffff, 2), "0");
1451+
assert_eq!(compute_largestexponent(0x7fffffff, 3), "0");
1452+
assert_eq!(compute_largestexponent(-0x7fffffff, 3), "0");
1453+
assert_eq!(compute_largestexponent(0x80000000, 1), "InputOutOfRange");
1454+
assert_eq!(compute_largestexponent(-0x80000000, 1), "InputOutOfRange");
1455+
assert_eq!(compute_largestexponent(0x80000001, 2), "InputOutOfRange");
1456+
assert_eq!(compute_largestexponent(-0x80000001, 2), "InputOutOfRange");
1457+
assert_eq!(compute_largestexponent(1, 0x7fffffff), "0");
1458+
assert_eq!(compute_largestexponent(1, -0x7fffffff), "0");
1459+
assert_eq!(compute_largestexponent(2, 0x7fffffff), "0");
1460+
assert_eq!(compute_largestexponent(2, -0x7fffffff), "0");
1461+
assert_eq!(compute_largestexponent(1, 0x80000000), "InputOutOfRange");
1462+
assert_eq!(compute_largestexponent(1, -0x80000000), "InputOutOfRange");
1463+
assert_eq!(compute_largestexponent(1, 0x80000001), "InputOutOfRange");
1464+
assert_eq!(compute_largestexponent(1, -0x80000001), "InputOutOfRange");
1465+
assert_eq!(compute_largestexponent(0x10000, 0x100), "2");
1466+
assert_eq!(compute_largestexponent(-0x10000, 0x100), "2");
1467+
assert_eq!(compute_largestexponent(0x1000000, 0x1000), "2");
1468+
assert_eq!(compute_largestexponent(-0x1000000, 0x1000), "2");
1469+
assert_eq!(compute_largestexponent(0x100000000, 0x10000), "InputOutOfRange");
1470+
assert_eq!(compute_largestexponent(-0x100000000, 0x10000), "InputOutOfRange");
1471+
assert_eq!(compute_largestexponent(0x10000000000, 0x100000), "InputOutOfRange");
1472+
assert_eq!(compute_largestexponent(-0x10000000000, 0x100000), "InputOutOfRange");
1473+
assert_eq!(compute_largestexponent(0x10000, -0x100), "2");
1474+
assert_eq!(compute_largestexponent(-0x10000, -0x100), "2");
1475+
assert_eq!(compute_largestexponent(0x1000000, -0x1000), "2");
1476+
assert_eq!(compute_largestexponent(-0x1000000, -0x1000), "2");
1477+
assert_eq!(compute_largestexponent(0x100000000, -0x10000), "InputOutOfRange");
1478+
assert_eq!(compute_largestexponent(-0x100000000, -0x10000), "InputOutOfRange");
1479+
assert_eq!(compute_largestexponent(0x10000000000, -0x100000), "InputOutOfRange");
1480+
assert_eq!(compute_largestexponent(-0x10000000000, -0x100000), "InputOutOfRange");
1481+
assert_eq!(compute_largestexponent(0x1000001, 0x1000), "0");
1482+
}
13451483
}

rust_project/loda-rust-core/src/execute/semantics.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub trait Semantics {
2323
fn nthroot(x: &BigInt, y: &BigInt) -> Result<BigInt, EvalError>;
2424
fn digitsum(x: &BigInt, y: &BigInt) -> Result<BigInt, EvalError>;
2525
fn digitalroot(x: &BigInt, y: &BigInt) -> Result<BigInt, EvalError>;
26+
fn largestexponent(x: &BigInt, y: &BigInt) -> Result<BigInt, EvalError>;
2627
fn equal(x: &BigInt, y: &BigInt) -> Result<BigInt, EvalError>;
2728
fn notequal(x: &BigInt, y: &BigInt) -> Result<BigInt, EvalError>;
2829
fn lessorequal(x: &BigInt, y: &BigInt) -> Result<BigInt, EvalError>;
@@ -143,6 +144,12 @@ impl Semantics for SemanticsWithoutLimits {
143144
Ok(value)
144145
}
145146

147+
fn largestexponent(x: &BigInt, y: &BigInt) -> Result<BigInt, EvalError> {
148+
let result: Result<BigInt, SemanticSimpleError> = semantic_simple::SEMANTIC_SIMPLE_CONFIG_UNLIMITED.compute_largestexponent(x, y);
149+
let value = result?;
150+
Ok(value)
151+
}
152+
146153
fn equal(x: &BigInt, y: &BigInt) -> Result<BigInt, EvalError> {
147154
let result: Result<BigInt, SemanticSimpleError> = semantic_simple::SEMANTIC_SIMPLE_CONFIG_UNLIMITED.compute_equal(x, y);
148155
let value = result?;
@@ -297,6 +304,12 @@ impl Semantics for SemanticsWithSmallLimits {
297304
Ok(value)
298305
}
299306

307+
fn largestexponent(x: &BigInt, y: &BigInt) -> Result<BigInt, EvalError> {
308+
let result: Result<BigInt, SemanticSimpleError> = semantic_simple::SEMANTIC_SIMPLE_CONFIG_LIMIT_SMALL.compute_largestexponent(x, y);
309+
let value = result?;
310+
Ok(value)
311+
}
312+
300313
fn equal(x: &BigInt, y: &BigInt) -> Result<BigInt, EvalError> {
301314
let result: Result<BigInt, SemanticSimpleError> = semantic_simple::SEMANTIC_SIMPLE_CONFIG_LIMIT_SMALL.compute_equal(x, y);
302315
let value = result?;

rust_project/loda-rust-core/src/parser/create_program.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,10 @@ impl CreateProgram {
466466
let node = self.create_node_calc(&instruction)?;
467467
program.push_boxed(node);
468468
},
469+
InstructionId::LargestExponent => {
470+
let node = self.create_node_calc(&instruction)?;
471+
program.push_boxed(node);
472+
},
469473
InstructionId::Equal => {
470474
let node = self.create_node_calc(&instruction)?;
471475
program.push_boxed(node);

rust_project/loda-rust-core/src/parser/instruction_id.rs

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ pub enum InstructionId {
1717
Equal,
1818
GCD,
1919
GreaterOrEqual,
20+
LargestExponent,
2021
LessOrEqual,
2122
Logarithm,
2223
LoopBegin,
@@ -38,35 +39,36 @@ pub enum InstructionId {
3839
impl fmt::Display for InstructionId {
3940
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4041
let s: &'static str = match self {
41-
Self::Add => "add",
42-
Self::Binomial => "bin",
43-
Self::BitwiseAnd => "ban",
44-
Self::BitwiseOr => "bor",
45-
Self::BitwiseXor => "bxo",
46-
Self::EvalSequence => "seq",
47-
Self::Compare => "cmp",
48-
Self::DigitalRoot => "dgr",
49-
Self::DigitSum => "dgs",
50-
Self::Divide => "div",
51-
Self::DivideIf => "dif",
52-
Self::DivideIfRepeat => "dir",
53-
Self::Equal => "equ",
54-
Self::GCD => "gcd",
55-
Self::GreaterOrEqual => "geq",
56-
Self::LessOrEqual => "leq",
57-
Self::Logarithm => "log",
58-
Self::LoopBegin => "lpb",
59-
Self::LoopEnd => "lpe",
60-
Self::Max => "max",
61-
Self::Min => "min",
62-
Self::Modulo => "mod",
63-
Self::Move => "mov",
64-
Self::Multiply => "mul",
65-
Self::NotEqual => "neq",
66-
Self::NthRoot => "nrt",
67-
Self::Power => "pow",
68-
Self::Subtract => "sub",
69-
Self::Truncate => "trn",
42+
Self::Add => "add",
43+
Self::Binomial => "bin",
44+
Self::BitwiseAnd => "ban",
45+
Self::BitwiseOr => "bor",
46+
Self::BitwiseXor => "bxo",
47+
Self::EvalSequence => "seq",
48+
Self::Compare => "cmp",
49+
Self::DigitalRoot => "dgr",
50+
Self::DigitSum => "dgs",
51+
Self::Divide => "div",
52+
Self::DivideIf => "dif",
53+
Self::DivideIfRepeat => "dir",
54+
Self::Equal => "equ",
55+
Self::GCD => "gcd",
56+
Self::GreaterOrEqual => "geq",
57+
Self::LargestExponent => "lex",
58+
Self::LessOrEqual => "leq",
59+
Self::Logarithm => "log",
60+
Self::LoopBegin => "lpb",
61+
Self::LoopEnd => "lpe",
62+
Self::Max => "max",
63+
Self::Min => "min",
64+
Self::Modulo => "mod",
65+
Self::Move => "mov",
66+
Self::Multiply => "mul",
67+
Self::NotEqual => "neq",
68+
Self::NthRoot => "nrt",
69+
Self::Power => "pow",
70+
Self::Subtract => "sub",
71+
Self::Truncate => "trn",
7072
Self::UnofficialFunction { input_count, output_count } => {
7173
return write!(f, "f{}{}", input_count, output_count);
7274
},

rust_project/loda-rust-core/src/parser/parse_instruction_id.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ impl ParseInstructionId for InstructionId {
3636
"equ" => Ok(Self::Equal),
3737
"gcd" => Ok(Self::GCD),
3838
"geq" => Ok(Self::GreaterOrEqual),
39+
"lex" => Ok(Self::LargestExponent),
3940
"log" => Ok(Self::Logarithm),
4041
"lpb" => Ok(Self::LoopBegin),
4142
"lpe" => Ok(Self::LoopEnd),
@@ -123,6 +124,10 @@ mod tests {
123124
let instruction_id: InstructionId = InstructionId::parse("dir", 1).expect("InstructionId");
124125
assert_eq!(instruction_id, InstructionId::DivideIfRepeat);
125126
}
127+
{
128+
let instruction_id: InstructionId = InstructionId::parse("lex", 1).expect("InstructionId");
129+
assert_eq!(instruction_id, InstructionId::LargestExponent);
130+
}
126131
{
127132
let instruction_id: InstructionId = InstructionId::parse("lps", 1).expect("InstructionId");
128133
assert_eq!(instruction_id, InstructionId::UnofficialLoopBeginSubtract);

rust_project/loda-rust-web/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ repository = "https://github.com/loda-lang/loda-rust"
77
license = "MIT OR Apache-2.0"
88
edition = "2021"
99

10+
[package.metadata.wasm-pack.profile.release]
11+
wasm-opt = false
12+
1013
[lib]
1114
crate-type = ["cdylib"]
1215

0 commit comments

Comments
 (0)