diff --git a/tools/data-conversion/src/fast_track.rs b/tools/data-conversion/src/fast_track.rs new file mode 100644 index 000000000..362f6e109 --- /dev/null +++ b/tools/data-conversion/src/fast_track.rs @@ -0,0 +1,361 @@ +use std::fs::File; +use std::io::stdout; +use std::io::{self, Write}; + +/// Formats [to_format] properly for float values +pub fn format_binary(to_format: u64) -> String { + let binary_str = format!("{:064b}", to_format); + format!( + "{} {} {}", + &binary_str[0..1], // Sign bit + &binary_str[1..9], // Exponent + &binary_str[9..] // Significand + ) +} + +pub fn format_hex(to_format: u64) -> String { + format!("0x{:X}", to_format) +} + +/// Converts a string representation of a floating-point number to its binary +/// format and appends the result to the specified file. +/// +/// This function takes a string slice representing a floating-point number, +/// converts it to a 64-bit floating-point number (`f64`), then converts this +/// number to its binary representation. The binary representation is formatted +/// as a string and written to the specified file, followed by a newline. +/// +/// # Arguments +/// +/// * `float_string` - A string slice containing the floating-point number to be converted. +/// * `filepath_send` - A mutable reference to a `File` where the binary representation +/// will be appended. +/// +/// # Returns +/// +/// This function returns a `std::io::Result<()>` which is `Ok` if the operation +/// is successful, or an `Err` if an I/O error occurs while writing to the file. +/// +/// # Panics +/// +/// This function will panic if the input string cannot be parsed as a floating-point number. +pub fn float_to_binary( + float_string: &str, + filepath_send: &mut Option, +) -> std::io::Result<()> { + let float_of_string: f64; + // Convert string to float + match float_string.parse::() { + Ok(parsed_num) => float_of_string = parsed_num, + Err(_) => { + panic!("Failed to parse float from string") + } + } + + // Convert float to binary + let binary_of_float = float_of_string.to_bits(); + let formatted_binary_str = format_binary(binary_of_float); + + if let Some(file) = filepath_send.as_mut() { + file.write_all(formatted_binary_str.as_bytes())?; + file.write_all(b"\n")?; + } else { + stdout().write_all(formatted_binary_str.as_bytes())?; + stdout().write_all(b"\n")?; + } + + Ok(()) +} + +/// Converts a string representation of a hexadecimal number to its binary +/// format and appends the result to the specified file. +/// +/// This function takes a string slice representing a hexadecimal number, +/// converts it to a 64-bit integer (`u64`), then converts this number to its +/// binary representation. The binary representation is formatted as a string +/// and written to the specified file, followed by a newline. +/// +/// # Arguments +/// +/// * `hex_string` - A string slice containing the hexadecimal number to be converted. +/// * `filepath_send` - A mutable reference to a `File` where the binary representation +/// will be appended. +/// +/// # Returns +/// +/// This function returns a `std::io::Result<()>` which is `Ok` if the operation +/// is successful, or an `Err` if an I/O error occurs while writing to the file. +/// +/// # Error +/// +/// This function will panic if the input string cannot be parsed as a hexadecimal number. +/// +/// This does not differentiate between floating and fixed. It just treats any hex as an integer. +pub fn hex_to_binary( + hex_string: &str, + filepath_send: &mut Option, +) -> io::Result<()> { + // Convert hex to binary + let binary_of_hex = u64::from_str_radix(hex_string, 16) + .expect("Failed to parse hex string"); + + // Format nicely + let formatted_binary_str = format!("{:b}", binary_of_hex); + + // Write binary string to the file + + if let Some(file) = filepath_send.as_mut() { + // Write binary string to the file + file.write_all(formatted_binary_str.as_bytes())?; + file.write_all(b"\n")?; + } else { + stdout().write_all(formatted_binary_str.as_bytes())?; + stdout().write_all(b"\n")?; + } + + Ok(()) +} + +/// Converts a string representation of a binary number to its hexadecimal +/// format and appends the result to the specified file. +/// +/// This function takes a string slice representing a binary number, +/// converts it to a 64-bit integer (`u64`), then converts this number to its +/// hexadecimal representation. The hexadecimal representation is formatted +/// as a string and written to the specified file, followed by a newline. +/// +/// # Arguments +/// +/// * `binary_string` - A string slice containing the binary number to be converted. +/// * `filepath_send` - A mutable reference to a `File` where the hexadecimal representation +/// will be appended. +/// +/// # Returns +/// +/// This function returns a `std::io::Result<()>` which is `Ok` if the operation +/// is successful, or an `Err` if an I/O error occurs while writing to the file. +/// +/// # Panics +/// +/// This function will panic if the input string cannot be parsed as a binary number. +pub fn binary_to_hex( + binary_string: &str, + filepath_send: &mut Option, +) -> io::Result<()> { + let hex_of_binary = u64::from_str_radix(binary_string, 2) + .expect("Failed to parse binary string"); + + let formatted_hex_str = format_hex(hex_of_binary); + + if let Some(file) = filepath_send.as_mut() { + // Write binary string to the file + file.write_all(formatted_hex_str.as_bytes())?; + file.write_all(b"\n")?; + } else { + stdout().write_all(formatted_hex_str.as_bytes())?; + stdout().write_all(b"\n")?; + } + + Ok(()) +} + +/// Converts a string representation of a binary number to its floating-point +/// format and appends the result to the specified file. +/// +/// This function takes a string slice representing a binary number, +/// converts it to a 64-bit integer (`u64`), then interprets this integer as +/// the binary representation of a 64-bit floating-point number (`f64`). +/// The floating-point representation is formatted as a string and written +/// to the specified file, followed by a newline. +/// +/// # Arguments +/// +/// * `binary_string` - A string slice containing the binary number to be converted. +/// * `filepath_send` - A mutable reference to a `File` where the floating-point representation +/// will be appended. +/// +/// # Returns +/// +/// This function returns a `std::io::Result<()>` which is `Ok` if the operation +/// is successful, or an `Err` if an I/O error occurs while writing to the file. +/// +/// # Panics +/// +/// This function will panic if the input string cannot be parsed as a binary number. +pub fn binary_to_float( + binary_string: &str, + filepath_send: &mut Option, +) -> io::Result<()> { + let binary_value = u64::from_str_radix(binary_string, 2) + .expect("Failed to parse binary string"); + + let formated_float_str = format!("{:?}", binary_value); + + if let Some(file) = filepath_send.as_mut() { + // Write binary string to the file + file.write_all(formated_float_str.as_bytes())?; + file.write_all(b"\n")?; + } else { + stdout().write_all(formated_float_str.as_bytes())?; + stdout().write_all(b"\n")?; + } + + Ok(()) +} + +/// Converts a string representation of a fixed-point number to its binary +/// format and appends the result to the specified file. +/// +/// This function takes a string slice representing a fixed-point number, +/// multiplies it by 2 raised to the power of the negative exponent, converts the result +/// to a 64-bit integer, and then to its binary representation. The binary representation +/// is formatted as a string and written to the specified file, followed by a newline. +/// +/// # Arguments +/// +/// * `fixed_string` - A string slice containing the fixed-point number to be converted. +/// * `filepath_send` - A mutable reference to a `File` where the binary representation +/// will be appended. +/// * `exponent` - A floating-point number representing the exponent to be applied in the +/// conversion process. +/// +/// # Returns +/// +/// This function returns a `std::io::Result<()>` which is `Ok` if the operation +/// is successful, or an `Err` if an I/O error occurs while writing to the file. +/// +/// # Panics +/// +/// This function will panic if the input string cannot be parsed as a fixed-point number. +pub fn fixed_to_binary( + fixed_string: &str, + filepath_send: &mut Option, + exp_int: i64, +) -> io::Result<()> { + // Convert fixed value from string to int + let fixed_value: f64; + match fixed_string.parse::() { + Ok(parsed_num) => fixed_value = parsed_num, + Err(_) => { + panic!("Bad fixed value input") + } + } + + //exponent int to float so we can multiply + let exponent = exp_int as f64; + + // Exponent math + let multiplied_fixed = fixed_value * 2_f64.powf(-exponent); + + // Convert to a 64-bit integer + let multiplied_fixed_as_i64 = multiplied_fixed as i64; + + // Convert to a binary string with 64 bits + let binary_of_fixed = format!("{:064b}", multiplied_fixed_as_i64); + + if let Some(file) = filepath_send.as_mut() { + // Write binary string to the file + file.write_all(binary_of_fixed.as_bytes())?; + file.write_all(b"\n")?; + } else { + stdout().write_all(binary_of_fixed.as_bytes())?; + stdout().write_all(b"\n")?; + } + + Ok(()) +} + +/// Converts a string representation of a binary number to its fixed-point +/// format and appends the result to the specified file. +/// +/// This function takes a string slice representing a binary number, +/// converts it to a 64-bit unsigned integer, interprets this integer as +/// a floating-point number, divides it by 2 raised to the power of the negative exponent, +/// and converts the result to its fixed-point representation. The fixed-point +/// representation is formatted as a string and written to the specified file, +/// followed by a newline. +/// +/// # Arguments +/// +/// * `binary_string` - A string slice containing the binary number to be converted. +/// * `filepath_send` - A mutable reference to a `File` where the fixed-point representation +/// will be appended. +/// * `exponent` - A floating-point number representing the exponent to be applied in the +/// conversion process. +/// +/// # Returns +/// +/// This function returns a `std::io::Result<()>` which is `Ok` if the operation +/// is successful, or an `Err` if an I/O error occurs while writing to the file. +/// +/// # Panics +/// +/// This function will panic if the input string cannot be parsed as a binary number. +pub fn binary_to_fixed( + binary_string: &str, + filepath_send: &mut Option, + exp_int: i64, +) -> io::Result<()> { + // Convert binary value from string to int + let binary_value = match u64::from_str_radix(binary_string, 2) { + Ok(parsed_num) => parsed_num, + Err(_) => panic!("Bad binary value input"), + }; + + // Convert to fixed + let int_of_binary = binary_value as f64; + + //exponent int to float so we can multiply + let exponent = exp_int as f64; + + // Exponent math + let divided: f64 = int_of_binary / 2_f64.powf(-exponent); + + let string_of_divided = format!("{:+.8e}", divided); + + if let Some(file) = filepath_send.as_mut() { + // Write binary string to the file + file.write_all(string_of_divided.as_bytes())?; + file.write_all(b"\n")?; + } else { + stdout().write_all(string_of_divided.as_bytes())?; + stdout().write_all(b"\n")?; + } + + Ok(()) +} + +pub fn binary_to_fixed_bit_slice( + binary_string: &str, + filepath_send: &mut Option, + exp_int: i64, +) -> io::Result<()> { + // Convert binary string to an integer (assuming binary_string is a valid binary representation) + let binary_int = u64::from_str_radix(binary_string, 2).unwrap(); + + // Adjust the binary point based on the exponent + let mut result = binary_int; + if exp_int < 0 { + // If exponent is negative, shift right (multiply by 2^(-exp_int)) + result >>= -exp_int as u64; + } else { + // If exponent is positive, shift left (multiply by 2^(exp_int)) + result <<= exp_int as u64; + } + + // Convert result to a fixed-point decimal representation + let fixed_value = result as f64; + + let string_of_fixed = format!("{:.8e}", fixed_value); + + if let Some(file) = filepath_send.as_mut() { + // Write binary string to the file + file.write_all(string_of_fixed.as_bytes())?; + file.write_all(b"\n")?; + } else { + stdout().write_all(string_of_fixed.as_bytes())?; + stdout().write_all(b"\n")?; + } + + Ok(()) +} diff --git a/tools/data-conversion/src/ir.rs b/tools/data-conversion/src/ir.rs index f800c848d..c45132510 100644 --- a/tools/data-conversion/src/ir.rs +++ b/tools/data-conversion/src/ir.rs @@ -6,10 +6,13 @@ use std::io::{self, Write}; use std::str::FromStr; +/// * 'sign' - `true` indicates that the value is negative; `false` indicates that it is positive. +/// * 'mantissa' - The absolute value represented as an integer without a decimal point. +/// * 'exponent' - The exponent to apply to the mantissa, where the actual value is calculated as `mantissa * 2^exponent`. The exponent can be negative. pub struct IntermediateRepresentation { - sign: bool, - mantissa: BigUint, - exponent: i64, + pub sign: bool, + pub mantissa: BigUint, + pub exponent: i64, } @@ -36,9 +39,16 @@ pub struct IntermediateRepresentation { pub fn from_binary( binary_string: &str, bit_width: usize, + twos_comp: bool, ) -> IntermediateRepresentation { - let sign = binary_string.starts_with('0'); + let sign; + if !twos_comp { + sign = false; + } else{ + sign = binary_string.starts_with('0'); + } + let binary_value = BigUint::from_str_radix(binary_string, 2) .expect("Invalid binary string"); diff --git a/tools/data-conversion/src/main.rs b/tools/data-conversion/src/main.rs index f8afa5cee..1cf257d04 100644 --- a/tools/data-conversion/src/main.rs +++ b/tools/data-conversion/src/main.rs @@ -1,33 +1,22 @@ use argh::FromArgs; -use num_bigint::BigUint; use std::error::Error; use std::fmt; use std::fs::read_to_string; use std::fs::File; -use std::io::stdout; -use std::io::{self, Write}; use std::str::FromStr; mod u8vector; mod ir; +mod fast_track; //cargo run -- --from $PATH1 --to $PATH2 --ftype "from" --totype "to" // Thresholds for using fast-track functions -const FAST_TRACK_THRESHOLD_BINARY_TO_FIXED: usize = 53; //52 bits for the significand (plus 1 implicit bit)b +// const FAST_TRACK_THRESHOLD_BINARY_TO_FIXED: usize = 53; //52 bits for the significand (plus 1 implicit bit)b +// const FAST_TRACK_THRESHOLD_FIXED_TO_BINARY: usize = 53; const FAST_TRACK_THRESHOLD_FLOAT_TO_BINARY: usize = 53; const FAST_TRACK_THRESHOLD_BINARY_TO_FLOAT: usize = 53; -const FAST_TRACK_THRESHOLD_FIXED_TO_BINARY: usize = 53; const FAST_TRACK_THRESHOLD_HEX_TO_BINARY: usize = 64; const FAST_TRACK_THRESHOLD_BINARY_TO_HEX: usize = 64; -/// * 'sign' - `true` indicates that the value is negative; `false` indicates that it is positive. -/// * 'mantissa' - The absolute value represented as an integer without a decimal point. -/// * 'exponent' - The exponent to apply to the mantissa, where the actual value is calculated as `mantissa * 2^exponent`. The exponent can be negative. -struct IntermediateRepresentation { - sign: bool, - mantissa: BigUint, - exponent: i64, -} - #[derive(Debug)] struct ParseNumTypeError; @@ -137,8 +126,8 @@ struct Arguments { #[argh(option)] tofile: FileType, - /// optional exponent for fixed_to_binary -> default is -1 - #[argh(option, default = "-1")] + /// optional exponent for fixed_to_binary -> default is -0 + #[argh(option, default = "0")] exp: i64, /// optional for fixed_to_binary using bit slicing. If choosen, will use bit slicing. @@ -151,7 +140,11 @@ struct Arguments { /// optional flag to force the inter-rep path #[argh(switch, short = 'i')] - inter: bool + inter: bool, + + /// optional flag - when flagged, will not use two's complement for binary + #[argh(switch, short = 't')] + twos: bool } fn main() { @@ -168,6 +161,7 @@ fn main() { args.bits, args.width, args.inter, + args.twos ); } @@ -199,6 +193,7 @@ fn convert( bits: bool, width: usize, inter: bool, + twos: bool ) { // Create the output file if filepath_send is Some let mut converted: Option = filepath_send @@ -211,7 +206,7 @@ fn convert( (FileType:: Hex, FileType::Binary) => { for line in read_to_string(filepath_get).unwrap().lines() { if line.len() <= FAST_TRACK_THRESHOLD_HEX_TO_BINARY && !inter{ - hex_to_binary(line, &mut converted) + fast_track::hex_to_binary(line, &mut converted) .expect("Failed to write binary to file"); } else { ir::to_binary(ir::from_hex(line, width), &mut converted, width) @@ -222,7 +217,7 @@ fn convert( (FileType:: Decimal, FileType::Binary)=>{ for line in read_to_string(filepath_get).unwrap().lines() { if line.len() <= FAST_TRACK_THRESHOLD_FLOAT_TO_BINARY && !inter { - float_to_binary(line, &mut converted) + fast_track::float_to_binary(line, &mut converted) .expect("Failed to write binary to file"); } else { ir::to_binary(ir::from_float(line), &mut converted, width) @@ -234,11 +229,11 @@ fn convert( for line in read_to_string(filepath_get).unwrap().lines() { print!("used fastpath"); if line.len() <= FAST_TRACK_THRESHOLD_BINARY_TO_HEX && !inter { - binary_to_hex(line, &mut converted) + fast_track::binary_to_hex(line, &mut converted) .expect("Failed to write hex to file"); } else { print!("used intermediate"); - ir::to_hex(ir::from_binary(line, width), &mut converted) + ir::to_hex(ir::from_binary(line, width, twos), &mut converted) .expect("Failed to write binary to file"); } } @@ -246,10 +241,10 @@ fn convert( (FileType:: Binary, FileType::Decimal)=>{ for line in read_to_string(filepath_get).unwrap().lines() { if line.len() <= FAST_TRACK_THRESHOLD_BINARY_TO_FLOAT && !inter { - binary_to_float(line, &mut converted) + fast_track::binary_to_float(line, &mut converted) .expect("Failed to write float to file"); } else { - ir::to_float(ir::from_binary(line, width), &mut converted) + ir::to_float(ir::from_binary(line, width, twos), &mut converted) .expect("Failed to write binary to file"); } } @@ -292,361 +287,3 @@ fn convert( ); } } - -/// Formats [to_format] properly for float values -fn format_binary(to_format: u64) -> String { - let binary_str = format!("{:064b}", to_format); - format!( - "{} {} {}", - &binary_str[0..1], // Sign bit - &binary_str[1..9], // Exponent - &binary_str[9..] // Significand - ) -} - -fn format_hex(to_format: u64) -> String { - format!("0x{:X}", to_format) -} - -/// Converts a string representation of a floating-point number to its binary -/// format and appends the result to the specified file. -/// -/// This function takes a string slice representing a floating-point number, -/// converts it to a 64-bit floating-point number (`f64`), then converts this -/// number to its binary representation. The binary representation is formatted -/// as a string and written to the specified file, followed by a newline. -/// -/// # Arguments -/// -/// * `float_string` - A string slice containing the floating-point number to be converted. -/// * `filepath_send` - A mutable reference to a `File` where the binary representation -/// will be appended. -/// -/// # Returns -/// -/// This function returns a `std::io::Result<()>` which is `Ok` if the operation -/// is successful, or an `Err` if an I/O error occurs while writing to the file. -/// -/// # Panics -/// -/// This function will panic if the input string cannot be parsed as a floating-point number. -fn float_to_binary( - float_string: &str, - filepath_send: &mut Option, -) -> std::io::Result<()> { - let float_of_string: f64; - // Convert string to float - match float_string.parse::() { - Ok(parsed_num) => float_of_string = parsed_num, - Err(_) => { - panic!("Failed to parse float from string") - } - } - - // Convert float to binary - let binary_of_float = float_of_string.to_bits(); - let formatted_binary_str = format_binary(binary_of_float); - - if let Some(file) = filepath_send.as_mut() { - file.write_all(formatted_binary_str.as_bytes())?; - file.write_all(b"\n")?; - } else { - stdout().write_all(formatted_binary_str.as_bytes())?; - stdout().write_all(b"\n")?; - } - - Ok(()) -} - -/// Converts a string representation of a hexadecimal number to its binary -/// format and appends the result to the specified file. -/// -/// This function takes a string slice representing a hexadecimal number, -/// converts it to a 64-bit integer (`u64`), then converts this number to its -/// binary representation. The binary representation is formatted as a string -/// and written to the specified file, followed by a newline. -/// -/// # Arguments -/// -/// * `hex_string` - A string slice containing the hexadecimal number to be converted. -/// * `filepath_send` - A mutable reference to a `File` where the binary representation -/// will be appended. -/// -/// # Returns -/// -/// This function returns a `std::io::Result<()>` which is `Ok` if the operation -/// is successful, or an `Err` if an I/O error occurs while writing to the file. -/// -/// # Error -/// -/// This function will panic if the input string cannot be parsed as a hexadecimal number. -/// -/// This does not differentiate between floating and fixed. It just treats any hex as an integer. -fn hex_to_binary( - hex_string: &str, - filepath_send: &mut Option, -) -> io::Result<()> { - // Convert hex to binary - let binary_of_hex = u64::from_str_radix(hex_string, 16) - .expect("Failed to parse hex string"); - - // Format nicely - let formatted_binary_str = format!("{:b}", binary_of_hex); - - // Write binary string to the file - - if let Some(file) = filepath_send.as_mut() { - // Write binary string to the file - file.write_all(formatted_binary_str.as_bytes())?; - file.write_all(b"\n")?; - } else { - stdout().write_all(formatted_binary_str.as_bytes())?; - stdout().write_all(b"\n")?; - } - - Ok(()) -} - -/// Converts a string representation of a binary number to its hexadecimal -/// format and appends the result to the specified file. -/// -/// This function takes a string slice representing a binary number, -/// converts it to a 64-bit integer (`u64`), then converts this number to its -/// hexadecimal representation. The hexadecimal representation is formatted -/// as a string and written to the specified file, followed by a newline. -/// -/// # Arguments -/// -/// * `binary_string` - A string slice containing the binary number to be converted. -/// * `filepath_send` - A mutable reference to a `File` where the hexadecimal representation -/// will be appended. -/// -/// # Returns -/// -/// This function returns a `std::io::Result<()>` which is `Ok` if the operation -/// is successful, or an `Err` if an I/O error occurs while writing to the file. -/// -/// # Panics -/// -/// This function will panic if the input string cannot be parsed as a binary number. -fn binary_to_hex( - binary_string: &str, - filepath_send: &mut Option, -) -> io::Result<()> { - let hex_of_binary = u64::from_str_radix(binary_string, 2) - .expect("Failed to parse binary string"); - - let formatted_hex_str = format_hex(hex_of_binary); - - if let Some(file) = filepath_send.as_mut() { - // Write binary string to the file - file.write_all(formatted_hex_str.as_bytes())?; - file.write_all(b"\n")?; - } else { - stdout().write_all(formatted_hex_str.as_bytes())?; - stdout().write_all(b"\n")?; - } - - Ok(()) -} - -/// Converts a string representation of a binary number to its floating-point -/// format and appends the result to the specified file. -/// -/// This function takes a string slice representing a binary number, -/// converts it to a 64-bit integer (`u64`), then interprets this integer as -/// the binary representation of a 64-bit floating-point number (`f64`). -/// The floating-point representation is formatted as a string and written -/// to the specified file, followed by a newline. -/// -/// # Arguments -/// -/// * `binary_string` - A string slice containing the binary number to be converted. -/// * `filepath_send` - A mutable reference to a `File` where the floating-point representation -/// will be appended. -/// -/// # Returns -/// -/// This function returns a `std::io::Result<()>` which is `Ok` if the operation -/// is successful, or an `Err` if an I/O error occurs while writing to the file. -/// -/// # Panics -/// -/// This function will panic if the input string cannot be parsed as a binary number. -fn binary_to_float( - binary_string: &str, - filepath_send: &mut Option, -) -> io::Result<()> { - let binary_value = u64::from_str_radix(binary_string, 2) - .expect("Failed to parse binary string"); - - let formated_float_str = format!("{:?}", binary_value); - - if let Some(file) = filepath_send.as_mut() { - // Write binary string to the file - file.write_all(formated_float_str.as_bytes())?; - file.write_all(b"\n")?; - } else { - stdout().write_all(formated_float_str.as_bytes())?; - stdout().write_all(b"\n")?; - } - - Ok(()) -} - -/// Converts a string representation of a fixed-point number to its binary -/// format and appends the result to the specified file. -/// -/// This function takes a string slice representing a fixed-point number, -/// multiplies it by 2 raised to the power of the negative exponent, converts the result -/// to a 64-bit integer, and then to its binary representation. The binary representation -/// is formatted as a string and written to the specified file, followed by a newline. -/// -/// # Arguments -/// -/// * `fixed_string` - A string slice containing the fixed-point number to be converted. -/// * `filepath_send` - A mutable reference to a `File` where the binary representation -/// will be appended. -/// * `exponent` - A floating-point number representing the exponent to be applied in the -/// conversion process. -/// -/// # Returns -/// -/// This function returns a `std::io::Result<()>` which is `Ok` if the operation -/// is successful, or an `Err` if an I/O error occurs while writing to the file. -/// -/// # Panics -/// -/// This function will panic if the input string cannot be parsed as a fixed-point number. -fn fixed_to_binary( - fixed_string: &str, - filepath_send: &mut Option, - exp_int: i64, -) -> io::Result<()> { - // Convert fixed value from string to int - let fixed_value: f64; - match fixed_string.parse::() { - Ok(parsed_num) => fixed_value = parsed_num, - Err(_) => { - panic!("Bad fixed value input") - } - } - - //exponent int to float so we can multiply - let exponent = exp_int as f64; - - // Exponent math - let multiplied_fixed = fixed_value * 2_f64.powf(-exponent); - - // Convert to a 64-bit integer - let multiplied_fixed_as_i64 = multiplied_fixed as i64; - - // Convert to a binary string with 64 bits - let binary_of_fixed = format!("{:064b}", multiplied_fixed_as_i64); - - if let Some(file) = filepath_send.as_mut() { - // Write binary string to the file - file.write_all(binary_of_fixed.as_bytes())?; - file.write_all(b"\n")?; - } else { - stdout().write_all(binary_of_fixed.as_bytes())?; - stdout().write_all(b"\n")?; - } - - Ok(()) -} - -/// Converts a string representation of a binary number to its fixed-point -/// format and appends the result to the specified file. -/// -/// This function takes a string slice representing a binary number, -/// converts it to a 64-bit unsigned integer, interprets this integer as -/// a floating-point number, divides it by 2 raised to the power of the negative exponent, -/// and converts the result to its fixed-point representation. The fixed-point -/// representation is formatted as a string and written to the specified file, -/// followed by a newline. -/// -/// # Arguments -/// -/// * `binary_string` - A string slice containing the binary number to be converted. -/// * `filepath_send` - A mutable reference to a `File` where the fixed-point representation -/// will be appended. -/// * `exponent` - A floating-point number representing the exponent to be applied in the -/// conversion process. -/// -/// # Returns -/// -/// This function returns a `std::io::Result<()>` which is `Ok` if the operation -/// is successful, or an `Err` if an I/O error occurs while writing to the file. -/// -/// # Panics -/// -/// This function will panic if the input string cannot be parsed as a binary number. -fn binary_to_fixed( - binary_string: &str, - filepath_send: &mut Option, - exp_int: i64, -) -> io::Result<()> { - // Convert binary value from string to int - let binary_value = match u64::from_str_radix(binary_string, 2) { - Ok(parsed_num) => parsed_num, - Err(_) => panic!("Bad binary value input"), - }; - - // Convert to fixed - let int_of_binary = binary_value as f64; - - //exponent int to float so we can multiply - let exponent = exp_int as f64; - - // Exponent math - let divided: f64 = int_of_binary / 2_f64.powf(-exponent); - - let string_of_divided = format!("{:+.8e}", divided); - - if let Some(file) = filepath_send.as_mut() { - // Write binary string to the file - file.write_all(string_of_divided.as_bytes())?; - file.write_all(b"\n")?; - } else { - stdout().write_all(string_of_divided.as_bytes())?; - stdout().write_all(b"\n")?; - } - - Ok(()) -} - -fn binary_to_fixed_bit_slice( - binary_string: &str, - filepath_send: &mut Option, - exp_int: i64, -) -> io::Result<()> { - // Convert binary string to an integer (assuming binary_string is a valid binary representation) - let binary_int = u64::from_str_radix(binary_string, 2).unwrap(); - - // Adjust the binary point based on the exponent - let mut result = binary_int; - if exp_int < 0 { - // If exponent is negative, shift right (multiply by 2^(-exp_int)) - result >>= -exp_int as u64; - } else { - // If exponent is positive, shift left (multiply by 2^(exp_int)) - result <<= exp_int as u64; - } - - // Convert result to a fixed-point decimal representation - let fixed_value = result as f64; - - let string_of_fixed = format!("{:.8e}", fixed_value); - - if let Some(file) = filepath_send.as_mut() { - // Write binary string to the file - file.write_all(string_of_fixed.as_bytes())?; - file.write_all(b"\n")?; - } else { - stdout().write_all(string_of_fixed.as_bytes())?; - stdout().write_all(b"\n")?; - } - - Ok(()) -} diff --git a/tools/data-conversion/src/u8vector.rs b/tools/data-conversion/src/u8vector.rs index 1e4db8d45..3083ce361 100644 --- a/tools/data-conversion/src/u8vector.rs +++ b/tools/data-conversion/src/u8vector.rs @@ -1,10 +1,14 @@ +use crate::ir::IntermediateRepresentation; +use num_bigint::{BigUint, BigInt}; + pub fn binary_to_u8_vec(binary: &str) -> Result, String> { - let mut padded_binary: String = binary.to_string(); + let mut padded_binary = binary.to_string(); - // If the binary string length is not a multiple of 8, pad it with leading zeros + // If the binary string length is not a multiple of 8, pad with the most significant bit let padding = 8 - (padded_binary.len() % 8); if padding != 8 { - padded_binary = "0".repeat(padding) + &padded_binary; + let msb = &padded_binary[0..1]; // Get the most significant bit + padded_binary = msb.repeat(padding) + &padded_binary; // Pad with the MSB } let mut vec = Vec::new(); @@ -20,39 +24,54 @@ pub fn binary_to_u8_vec(binary: &str) -> Result, String> { Ok(vec) } + pub fn hex_to_u8_vec(hex: &str) -> Result, String> { let mut padded_hex = hex.to_string(); + // If the hex string length is not a multiple of 2, pad with the most significant nibble let padding = 2 - (padded_hex.len() % 2); if padding != 2 { - padded_hex = "0".repeat(padding) + &padded_hex; + let msb = &padded_hex[0..1]; // Get the most significant nibble + padded_hex = msb.repeat(padding) + &padded_hex; // Pad with the MSB } let mut vec = Vec::new(); for i in (0..padded_hex.len()).step_by(2) { - let byte_str = &padded_hex[i..i + 8]; - match u8::from_str_radix(byte_str, 2){ + let byte_str = &padded_hex[i..i + 2]; // Fixed to extract two hex digits + match u8::from_str_radix(byte_str, 16) { Ok(byte) => vec.push(byte), - Err(_) => return Err(String::from("Invalid binary string")), + Err(_) => return Err(String::from("Invalid hex string")), } } Ok(vec) } -pub fn decimal_to_u8_vec(decimal: &str) -> Result, String> { - let mut vec = Vec::new(); - // Iterate over each character in the decimal string - for c in decimal.chars() { - // Check if the character is a digit - if let Some(digit) = c.to_digit(10) { - // Convert the digit (u32) to a u8 and push it to the vector - vec.push(digit as u8); - } else { - return Err(format!("Invalid character '{}' in decimal string", c)); +pub fn u8_to_ir(vector: Result, String>, exponent: i64) -> IntermediateRepresentation { + match vector { + Ok(vec) => { + // Check if the MSB of the first byte is 1 + let is_negative = (vec[0] & 0b10000000) != 0; + + let mantissa = if is_negative { + // Convert the Vec to a two's complement BigInt, then get its absolute value + let bigint = BigInt::from_signed_bytes_be(&vec); + bigint.magnitude().clone() // absolute value + } else { + BigUint::from_bytes_be(&vec) + }; + + IntermediateRepresentation { + sign: is_negative, + mantissa, + exponent, + } + } + Err(e) => { + // Handle the error case, for example by panicking or returning a default value. + panic!("Failed to convert: {}", e); } } - Ok(vec) } \ No newline at end of file