Skip to content

Commit

Permalink
Add support for various operation with double
Browse files Browse the repository at this point in the history
  • Loading branch information
hextriclosan committed Oct 16, 2024
1 parent 93a4736 commit 6e3f1c1
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 0 deletions.
9 changes: 9 additions & 0 deletions tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,15 @@ fn should_do_subtraction_with_doubles() {
assert_eq!(-8.76543211E200, get_double(last_frame_value))
}

#[test]
fn should_do_operations_with_doubles() {
let mut vm = VM::new("std");
let last_frame_value = vm
.run("samples.arithmetics.operations.doubles.DoubleOperations")
.unwrap();
assert_eq!(2.8547008547008547E278, get_double(last_frame_value))
}

#[test]
fn should_do_trivial_cast() {
let mut vm = VM::new("std");
Expand Down
28 changes: 28 additions & 0 deletions tests/test_data/DoubleOperations.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package samples.arithmetics.operations.doubles;

public class DoubleOperations {
public static void main(String[] args) {
// Large and small values
double large = 1.989e30; // Mass of the Sun (kg)
double small = 1.8549e-43; // Planck time (s)
double tiny = 5e-324; // Smallest positive double
double huge = 1.7e308; // Largest double

// Arithmetic operations
double sum = large + huge; // Addition with large numbers
double diff = huge - large; // Subtraction with large numbers
double product = small * tiny; // Multiplication with small numbers
double quotient = huge / large; // Division with large numbers
double remainder = huge % large; // Modulus operation


// Special cases
double underflow = small / large; // Underflow: tiny result
double overflow = huge * huge; // Overflow: exceeds max double
double nan = 0.0 / 0.0; // NaN (Not a Number)

double result = sum/1e100 + diff/1e100 + product + quotient + remainder + underflow +
(overflow == Double.POSITIVE_INFINITY ? 1e278 : 0) +
(Double.isNaN(nan) ? 1e278 : 0);
}
}
Binary file not shown.
92 changes: 92 additions & 0 deletions vm/src/execution_engine/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,18 @@ impl Engine {
stack_frame.incr_pc();
println!("LLOAD -> pos={pos}, value={value}");
}
DLOAD => {
stack_frame.incr_pc();
let pos = stack_frame.get_bytecode_byte() as usize;

let (low, high, value) = stack_frame.get_two_bytes_from_local(pos);

stack_frame.push(low);
stack_frame.push(high);

stack_frame.incr_pc();
println!("DLOAD -> pos={pos}, value={value}");
}
ALOAD => {
stack_frame.incr_pc();
let index = stack_frame.get_bytecode_byte() as usize;
Expand Down Expand Up @@ -240,6 +252,15 @@ impl Engine {
stack_frame.incr_pc();
println!("FLOAD_1 -> value={value}");
}
DLOAD_0 => {
let (low, high, value) = stack_frame.get_two_bytes_from_local(0);

stack_frame.push(low);
stack_frame.push(high);

stack_frame.incr_pc();
println!("DLOAD_0 -> value={value}");
}
DLOAD_1 => {
let (low, high, value) = stack_frame.get_two_bytes_from_local(1);

Expand Down Expand Up @@ -642,6 +663,17 @@ impl Engine {
stack_frame.incr_pc();
println!("LADD -> {a} + {b} = {result}");
}
DADD => {
let b = f64::from_bits(stack_frame.pop_i64() as u64);
let a = f64::from_bits(stack_frame.pop_i64() as u64);

let result = a + b;

stack_frame.push_i64(result.to_bits() as i64);

stack_frame.incr_pc();
println!("DADD -> {a} + {b} = {result}");
}
ISUB => {
let b = stack_frame.pop();
let a = stack_frame.pop();
Expand Down Expand Up @@ -702,6 +734,17 @@ impl Engine {
stack_frame.incr_pc();
println!("LMUL -> {a} * {b} = {result}");
}
DMUL => {
let b = f64::from_bits(stack_frame.pop_i64() as u64);
let a = f64::from_bits(stack_frame.pop_i64() as u64);

let result = a * b;

stack_frame.push_i64(result.to_bits() as i64);

stack_frame.incr_pc();
println!("DMUL -> {a} * {b} = {result}");
}
IDIV => {
let b = stack_frame.pop();
let a = stack_frame.pop();
Expand All @@ -711,6 +754,17 @@ impl Engine {
stack_frame.incr_pc();
println!("IDIV -> {a} / {b} = {result}");
}
DDIV => {
let b = f64::from_bits(stack_frame.pop_i64() as u64);
let a = f64::from_bits(stack_frame.pop_i64() as u64);

let result = a / b;

stack_frame.push_i64(result.to_bits() as i64);

stack_frame.incr_pc();
println!("DDIV -> {a} / {b} = {result}");
}
IREM => {
let b = stack_frame.pop();
let a = stack_frame.pop();
Expand All @@ -731,6 +785,17 @@ impl Engine {
stack_frame.incr_pc();
println!("LREM -> {a} % {b} = {result}");
}
DREM => {
let b = f64::from_bits(stack_frame.pop_i64() as u64);
let a = f64::from_bits(stack_frame.pop_i64() as u64);

let result = a % b;

stack_frame.push_i64(result.to_bits() as i64);

stack_frame.incr_pc();
println!("DREM -> {a} % {b} = {result}");
}
ISHL => {
let b = stack_frame.pop();
let a = stack_frame.pop();
Expand Down Expand Up @@ -825,6 +890,14 @@ impl Engine {
stack_frame.incr_pc();
println!("I2F -> {value}F");
}
I2D => {
let value = stack_frame.pop() as f64;

stack_frame.push_i64(value.to_bits() as i64);

stack_frame.incr_pc();
println!("I2D -> {value}D");
}
I2B => {
let value = stack_frame.pop() as i8;

Expand Down Expand Up @@ -856,6 +929,25 @@ impl Engine {
stack_frame.incr_pc();
println!("LCMP -> {a} ? {b}");
}
DCMPL => {
let b = f64::from_bits(stack_frame.pop_i64() as u64);
let a = f64::from_bits(stack_frame.pop_i64() as u64);

let result = if a.is_nan() || b.is_nan() {
-1
} else if a < b {
-1
} else if a > b {
1
} else {
0
};

stack_frame.push(result);

stack_frame.incr_pc();
println!("DCMPL -> {a} ? {b}");
}
IFEQ => {
let value = stack_frame.pop();
let offset = Self::get_two_bytes_ahead(stack_frame);
Expand Down

0 comments on commit 6e3f1c1

Please sign in to comment.