Expand description
§SignVec
SignVec
extends the capabilities of the traditional Vec
by providing additional functionalities
to efficiently track and manipulate elements based on their sign (positive or negative) using the Signable
trait.
§Features
- Sign-Aware Element Tracking: Tracks the sign of elements for optimized sign-specific operations.
- Efficient Updates: Maintains high performance even with frequent modifications.
- Versatile Operations: Provides methods for element counting, access, and manipulation based on sign.
- Flexible Interface: Offers both safe and unsafe methods to accommodate various requirements.
- Custom Type Support: Seamlessly integrates with user-defined types via the
Signable
trait.
§Usage: Basic operations
use nanorand::{Rng, WyRand};
use signvec::{svec, Sign, SignVec};
let mut vector = svec![1, -2, 3, -4];
assert_eq!(vector.len(), 4);
assert_eq!(vector[0], 1);
assert_eq!(vector[1], -2);
// Count positive and negative elements
assert_eq!(vector.count(Sign::Plus), 2);
assert_eq!(vector.count(Sign::Minus), 2);
// Get indices of positive and negative elements
assert_eq!(
vector.indices(Sign::Plus).iter().collect::<Vec<_>>(),
vec![&0, &2]
);
assert_eq!(
vector.indices(Sign::Minus).iter().collect::<Vec<_>>(),
vec![&1, &3]
);
// Retrieve values based on their sign
assert_eq!(vector.values(Sign::Plus).collect::<Vec<_>>(), vec![&1, &3]);
assert_eq!(
vector.values(Sign::Minus).collect::<Vec<_>>(),
vec![&-2, &-4]
);
// Modify individual elements
vector.set(1, 5);
assert_eq!(vector[1], 5);
// Randomly select an element based on its sign
let mut rng = WyRand::new();
if let Some(random_positive) = vector.random(Sign::Plus, &mut rng) {
println!("Random positive value: {}", random_positive);
}
§Usage: Monte Carlo simulations
This demonstrates a simple Monte Carlo simulation where site energies in a
SignVec
are updated based on simulated dynamics and system energy distribution.
use signvec::{SignVec, svec, Sign, Signable};
use nanorand::{WyRand, Rng};
let mut energies = svec![1.0, -1.0, 1.5, -1.5, 0.5, -0.5];
let mut rng = WyRand::new();
// Simulation loop for multiple Monte Carlo steps
for _step in 0..100 {
let site = rng.generate_range(0..energies.len());
let dE = rng.generate::<f64>() - 0.5; // Change in energy
let new_energy = energies[site] + dE; // Update site energy
// Make decisions based on system's energy distribution
if energies.count(Sign::Minus) > energies.count(Sign::Plus) {
if energies[site].sign() == Sign::Minus && rng.generate::<f64>() < 0.5 {
energies.set(site, -new_energy); // Flip energy sign
} else {
energies.set(site, new_energy);
}
} else {
energies.set(site, new_energy); // Balanced distribution
}
}
println!("Final energy distribution: {:?}", energies);
§Usage: Portfolio management
Demonstrates how SignVec
can be used for managing a financial portfolio, simulating
market conditions, and making decisions based on the sign-aware characteristics of
assets and liabilities.
use signvec::{SignVec, Sign, svec};
use nanorand::WyRand;
let mut portfolio = svec![150.0, -200.0, 300.0, -50.0, 400.0];
let market_conditions = vec![1.05, 0.95, 1.10, 1.00, 1.03];
// Apply market conditions to adjust portfolio balances
for (index, &factor) in market_conditions.iter().enumerate() {
portfolio.set(index, portfolio[index] * factor);
}
// Decision making based on portfolio's sign-aware characteristics
if portfolio.count(Sign::Minus) > 2 {
println!("Consider rebalancing your portfolio to manage risk.");
} else {
println!("Your portfolio is well-balanced and diversified.");
}
// Calculate 10% of total liabilities for debt reduction
let debt_reduction = portfolio.values(Sign::Minus).sum::<f64>() * 0.1;
println!("Plan for a debt reduction of ${:.2} to strengthen your financial position.", debt_reduction.abs());
// Identify a high-performing asset for potential investment
let mut rng = WyRand::new();
if let Some(lucky_asset) = portfolio.random(Sign::Plus, &mut rng) {
println!("Consider investing more in an asset valued at ${:.2}.", lucky_asset);
} else {
println!("No standout assets for additional investment at the moment.");
}
§Benchmarks
The table below is a summary of benchmark results for the specialized functionality of SignVec
.
Operation | SignVec | Vec | Speedup |
---|---|---|---|
set | 1.3922 ns | - | - |
set_unchecked | 1.3873 ns | - | - |
random (Plus) | 822.90 ps | - | - |
random (Minus) | 829.92 ps | - | - |
random_pos | 652.96 ps | - | - |
random_neg | 687.77 ps | - | - |
count (Plus) | 453.21 ps | - | - |
count (Minus) | 458.70 ps | - | - |
count_pos | 229.73 ps | - | - |
count_neg | 228.44 ps | - | - |
indices (Plus) | 465.04 ps | - | - |
indices (Minus) | 461.85 ps | - | - |
indices_pos | 226.99 ps | - | - |
indices_neg | 225.83 ps | - | - |
sync | 61.208 µs | - | - |
count 1 | 225.74 ps | 153.38 ns | ~679x faster |
indices 2 | 86.42 ns | 1.11 µs | ~12.8x faster |
values 3 | 579.37 ns | 1.13 µs | ~1.95x faster |
random 4 | 857.86 ps | 950.84 ns | ~1106x faster |
Benchmarks were conducted on a machine with the following specifications:
- Processor: AMD Ryzen™ 5 5600G with Radeon™ Graphics x 12
- Memory: 58.8 GiB
- Operating System: Guix System
- OS Type: 64-bit
The
count_pos
andcount_neg
benchmarks are used here for comparison as they represent the optimized paths for counting elements by sign. ↩The
indices_pos
andindices_neg
benchmarks are presented as the optimized methods for retrieving indices by sign. ↩The
values
operation does not have a direct counterpart in the provided benchmarks but is included for context. ↩The
random_pos
andrandom_neg
benchmarks provide context for therandom
operation’s performance when the sign is predetermined. ↩
Macros§
Structs§
- SignVec
- A vector-like data structure with additional information about the sign of its elements.
Enums§
- Sign
- Enum representing the sign of a number.
Traits§
- Signable
- Trait for types that can be classified by a sign.