Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

math: more type tests #6713

Merged
merged 3 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions libraries/math/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,43 @@ pub enum MathInstruction {
exponent: f64,
},

/// Multiply two u128 values
///
/// No accounts required for this instruction
U128Multiply {
/// The multiplicand
multiplicand: u128,
/// The multipier
multiplier: u128,
},
/// Divide two u128 values
///
/// No accounts required for this instruction
U128Divide {
/// The dividend
dividend: u128,
/// The divisor
divisor: u128,
},
/// Multiply two f64 values
///
/// No accounts required for this instruction
F64Multiply {
/// The multiplicand
multiplicand: f64,
/// The multipier
multiplier: f64,
},
/// Divide two f64 values
///
/// No accounts required for this instruction
F64Divide {
/// The dividend
dividend: f64,
/// The divisor
divisor: f64,
},

/// Don't do anything for comparison
///
/// No accounts required for this instruction
Expand Down Expand Up @@ -220,6 +257,50 @@ pub fn f64_pow(base: f64, exponent: f64) -> Instruction {
}
}

/// Create U128 Multiplication instruction
pub fn u128_multiply(multiplicand: u128, multiplier: u128) -> Instruction {
Instruction {
program_id: id(),
accounts: vec![],
data: borsh::to_vec(&MathInstruction::U128Multiply {
multiplicand,
multiplier,
})
.unwrap(),
}
}

/// Create U128 Division instruction
pub fn u128_divide(dividend: u128, divisor: u128) -> Instruction {
Instruction {
program_id: id(),
accounts: vec![],
data: borsh::to_vec(&MathInstruction::U128Divide { dividend, divisor }).unwrap(),
}
}

/// Create F64 Multiplication instruction
pub fn f64_multiply(multiplicand: f64, multiplier: f64) -> Instruction {
Instruction {
program_id: id(),
accounts: vec![],
data: borsh::to_vec(&MathInstruction::F64Multiply {
multiplicand,
multiplier,
})
.unwrap(),
}
}

/// Create F64 Division instruction
pub fn f64_divide(dividend: f64, divisor: f64) -> Instruction {
Instruction {
program_id: id(),
accounts: vec![],
data: borsh::to_vec(&MathInstruction::F64Divide { dividend, divisor }).unwrap(),
}
}

/// Create Noop instruction
pub fn noop() -> Instruction {
Instruction {
Expand Down
62 changes: 62 additions & 0 deletions libraries/math/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,30 @@ fn f32_natural_log(argument: f32) -> f32 {
argument.ln()
}

/// u128_multiply
#[inline(never)]
fn u128_multiply(multiplicand: u128, multiplier: u128) -> u128 {
multiplicand * multiplier
}

/// u128_divide
#[inline(never)]
fn u128_divide(dividend: u128, divisor: u128) -> u128 {
dividend / divisor
}

/// f64_multiply
#[inline(never)]
fn f64_multiply(multiplicand: f64, multiplier: f64) -> f64 {
multiplicand * multiplier
}

/// f64_divide
#[inline(never)]
fn f64_divide(dividend: f64, divisor: f64) -> f64 {
dividend / divisor
}

/// Instruction processor
pub fn process_instruction(
_program_id: &Pubkey,
Expand Down Expand Up @@ -157,6 +181,44 @@ pub fn process_instruction(
msg!("{}", result as u64);
Ok(())
}
MathInstruction::U128Multiply {
multiplicand,
multiplier,
} => {
msg!("Calculating u128 Multiply");
sol_log_compute_units();
let result = u128_multiply(multiplicand, multiplier);
sol_log_compute_units();
msg!("{}", result);
Ok(())
}
MathInstruction::U128Divide { dividend, divisor } => {
msg!("Calculating u128 Divide");
sol_log_compute_units();
let result = u128_divide(dividend, divisor);
sol_log_compute_units();
msg!("{}", result);
Ok(())
}
MathInstruction::F64Multiply {
multiplicand,
multiplier,
} => {
msg!("Calculating f64 Multiply");
sol_log_compute_units();
let result = f64_multiply(multiplicand, multiplier);
sol_log_compute_units();
msg!("{}", result as u64);
Ok(())
}
MathInstruction::F64Divide { dividend, divisor } => {
msg!("Calculating f64 Divide");
sol_log_compute_units();
let result = f64_divide(dividend, divisor);
sol_log_compute_units();
msg!("{}", result as u64);
Ok(())
}
MathInstruction::Noop => {
msg!("Do nothing");
msg!("{}", 0_u64);
Expand Down
64 changes: 64 additions & 0 deletions libraries/math/tests/instruction_count.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,70 @@ async fn test_f64_pow() {
banks_client.process_transaction(transaction).await.unwrap();
}

#[tokio::test]
async fn test_u128_multiply() {
let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));

pc.set_compute_max_units(10000);

let (mut banks_client, payer, recent_blockhash) = pc.start().await;

let mut transaction = Transaction::new_with_payer(
&[instruction::u128_multiply(u64::MAX.into(), u64::MAX.into())],
Some(&payer.pubkey()),
);
transaction.sign(&[&payer], recent_blockhash);
banks_client.process_transaction(transaction).await.unwrap();
}

#[tokio::test]
async fn test_u128_divide() {
let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));

pc.set_compute_max_units(10000);

let (mut banks_client, payer, recent_blockhash) = pc.start().await;

let mut transaction = Transaction::new_with_payer(
&[instruction::u128_divide(u128::MAX, u128::MAX / 69)],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

Some(&payer.pubkey()),
);
transaction.sign(&[&payer], recent_blockhash);
banks_client.process_transaction(transaction).await.unwrap();
}

#[tokio::test]
async fn test_f64_multiply() {
let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));

pc.set_compute_max_units(10000);

let (mut banks_client, payer, recent_blockhash) = pc.start().await;

let mut transaction = Transaction::new_with_payer(
&[instruction::f64_multiply(f64::powf(2., 42.), 1e-4)],
Some(&payer.pubkey()),
);
transaction.sign(&[&payer], recent_blockhash);
banks_client.process_transaction(transaction).await.unwrap();
}

#[tokio::test]
async fn test_f64_divide() {
let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));

pc.set_compute_max_units(10000);

let (mut banks_client, payer, recent_blockhash) = pc.start().await;

let mut transaction = Transaction::new_with_payer(
&[instruction::f64_divide(f64::powf(2., 42.), 420420.6969)],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice nice

Some(&payer.pubkey()),
);
transaction.sign(&[&payer], recent_blockhash);
banks_client.process_transaction(transaction).await.unwrap();
}

#[tokio::test]
async fn test_noop() {
let mut pc = ProgramTest::new("spl_math", id(), processor!(process_instruction));
Expand Down