All the functions and their inverses below work, with the exception of: sine and cosine. The hyperbolic versions of each work, but the base functions do not. The assertions fail when: the random value which determines which function to use happens to choose sine or cosine, then the inverse does not map correctly to the original input:
/// applies a pseudo-random function to the input. This is used to produce a secure value which identifies a packet.
///
/// It is close to necessary for the drill to be used in order to find the correct values, since `op_value` comes from
/// the drill. The produced floating point value must be correct forall digits
///
/// Produces a floating-point number. All functions must necessarily be surjective
#[inline]
fn get_op_result_by_input(op_value: u8, coefficient: u32, input: u32) -> f64 {
println!("op_value: {}", op_value);
println!("{} * op({})", coefficient, input);
let input = input as f64;
match op_value {
0..32 => {
coefficient as f64 * (input).ln()
},
32..64 => {
coefficient as f64 * (input).sin()
},
64..96 => {
coefficient as f64 * (input).cos()
},
96..128 => {
coefficient as f64 * (input).tan()
},
128..160 => {
coefficient as f64 * (input).sinh()
},
160..192 => {
coefficient as f64 * (input).cosh()
},
192..224 => {
coefficient as f64 * (input).tanh()
},
224..=255 => {
coefficient as f64 * (input).recip()
}
}
}
#[inline]
fn get_op_result_by_input_inv(op_value: u8, coefficient: u32, input: f64) -> usize {
println!("op_value: {}", op_value);
let ka = input / f64::from(coefficient);
println!("{} / {} = ka == {}", coefficient, input, ka);
match op_value {
// natural log
0..32 => {
ka.exp().round() as usize
},
32..64 => {
ka.asin().round() as usize
},
64..96 => {
ka.acos().round() as usize
},
96..128 => {
ka.atan().round() as usize
},
128..160 => {
ka.asinh().round() as usize
},
160..192 => {
ka.acosh().round() as usize
},
192..224 => {
ka.atanh().round() as usize
},
224..=255 => {
ka.recip().round() as usize
}
}
}
/// `x` should be the packet number in the wave
pub fn calculate_pid<Drx: DrillType>(x: usize, drill: &Drx) -> f64 {
get_op_result_by_input(drill.get_low()[VIRTUAL_TIME_INDEX][0], drill.get_high()[VIRTUAL_TIME_INDEX][0], x as u32)
}
#[inline]
/// The inverse function of `calculate_pid`
pub fn calculate_pid_inv<Drx: DrillType>(y: f64, drill: &Drx) -> usize {
get_op_result_by_input_inv(drill.get_low()[VIRTUAL_TIME_INDEX][0], drill.get_high()[VIRTUAL_TIME_INDEX][0], y)
}
/// `x` should be the wave number in the wave series
pub fn calculate_wid<Drx: DrillType>(x: usize, drill: &Drx) -> f64 {
get_op_result_by_input(drill.get_low()[VIRTUAL_TIME_INDEX][1], drill.get_high()[VIRTUAL_TIME_INDEX][1], x as u32)
}
#[inline]
/// The inverse function of `calculate_wid`
pub fn calculate_wid_inv<Drx: DrillType>(y: f64, drill: &Drx) -> usize {
get_op_result_by_input_inv(drill.get_low()[VIRTUAL_TIME_INDEX][1], drill.get_high()[VIRTUAL_TIME_INDEX][1], y)
}