use crate::linalg::{Matrix, Tensor};
use crate::{Float, Num};
use rayon::prelude::IntoParallelRefMutIterator;
use rayon::prelude::*;
use std::cmp::{min, Ordering};
use std::fmt::{Debug, Display, Formatter};
use std::ops::{Add, AddAssign, Index, IndexMut, Mul, MulAssign, Sub, SubAssign};
#[macro_export]
macro_rules! vector {
($($x:expr),*) => {
Vector::from(
vec![
$($x,)*
]
)
};
}
#[derive(PartialEq, Eq, Debug)]
pub struct Vector<T: Num> {
pub(crate) data: Vec<T>,
pub(crate) length: usize,
}
impl<T: Num> Vector<T> {
pub fn from_num(num: T, length: usize) -> Self {
Self::from(vec![num; length])
}
pub fn scalar(&self, other: &Vector<T>) -> T {
let mut output = T::default();
for i in 0..min(self.data.len(), other.data.len()) {
output += self[i].clone() * other[i].clone();
}
output
}
pub fn get_data(&self) -> Vec<T> {
self.data.clone()
}
pub fn range(start: T, end: T, step: T) -> Result<Self, &'static str> {
if step == T::default() {
return Err("!!!Step cannot be zero.!!!");
}
if (start < end && step < T::default()) || (start > end && step > T::default()) {
return Err("!!!Invalid range: step direction does not match range direction.!!!");
}
let mut data = vec![];
let mut number = start;
while (step > T::from(0) && number < end) || (step < T::from(0) && number > end) {
data.push(number);
number += step;
}
Ok(Vector {
length: data.len(),
data,
})
}
pub fn len(&self) -> usize {
self.length
}
pub fn clone(&self) -> Vector<T> {
Vector {
data: self.data.clone(),
length: self.length,
}
}
pub fn resize(&self, new_length: usize) -> Vector<T> {
let mut new_data = Vec::new();
for i in &self.data {
new_data.push((*i).clone());
}
new_data.resize(new_length, T::default());
Self {
data: new_data.to_owned(),
length: new_length,
}
}
pub fn sum_all(&self) -> T {
let mut sum = T::default();
for i in &self.data {
sum += i.clone();
}
sum
}
pub fn abs_sum(self) -> T {
let mut sum = T::default();
for i in self.data {
if i < T::default() {
sum -= i
} else {
sum += i
}
}
sum
}
pub fn try_from(value: Tensor<T>) -> Result<Self, &'static str> {
if value.shape.len() != 1 {
return Err("Shape size must be 1");
}
Ok(Vector::from(value.data))
}
pub fn map_vec<F>(&self, f: F) -> Vector<T>
where
F: Fn(T) -> T + Sync + Send,
{
let new_data = self.data.clone().par_iter_mut().map(|x| f(*x)).collect();
Self {
data: new_data,
length: self.length,
}
}
pub fn max_val(&self) -> Option<T> {
if self.data.len() == 0 {
return None
}
let mut max_value = self.data[0];
for i in 1..self.data.len() {
if self.data[i] > max_value {
max_value = self.data[i];
}
}
Some(max_value)
}
pub fn outer(&self, other: &Vector<T>) -> Matrix<T> {
let mut result_data = vec![T::default(); self.length * other.length];
result_data
.par_iter_mut()
.enumerate()
.for_each(|(idx, val)| {
let i = idx / other.length;
let j = idx % other.length;
*val = self.data[i] * other.data[j];
});
Matrix {
data: result_data,
rows: self.length,
cols: other.length,
}
}
pub fn table<F>(&self, other: &Vector<T>, f: F) -> Matrix<T>
where
F: Fn(T, T) -> T + Sync + Send{
let mut result_data = vec![T::default(); self.length * other.length];
result_data
.par_iter_mut()
.enumerate()
.for_each(|(idx, val)| {
let i = idx / other.length;
let j = idx % other.length;
*val = f(self.data[i], other.data[j]);
});
Matrix {
data: result_data,
rows: self.length,
cols: other.length,
}
}
pub fn argmax(&self) -> usize {
self.data
.iter()
.enumerate()
.max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Equal))
.map(|(index, _)| index)
.unwrap_or(0)
}
}
impl<T: Num> Index<usize> for Vector<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
if index > self.length {
panic!("!!!Vector index out of bounds!!!");
}
&self.data[index]
}
}
impl<T: Num> IndexMut<usize> for Vector<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
if index > self.length {
panic!("!!!Vector index out of bounds!!!");
}
&mut self.data[index]
}
}
impl<T: Float> Vector<T> {
pub fn linspace(start: T, stop:T, num:usize, endpoint:bool) -> Self{
if num == 1 {
return Vector{
data: vec![start],
length: 1
};
}
let step = if endpoint {
(stop - start) / (T::from_usize(num) - T::one())
} else {
(stop - start) / T::from_usize(num)
};
let data = vec![T::one(); num].iter().enumerate().map(|(i, _)| {
start + (T::from_usize(i) * step)
}).collect();
Self {
data,
length: num,
}
}
pub fn length(self) -> T {
let mut ans = T::default();
for i in self {
ans += i * i;
}
ans.sqrt()
}
pub fn exp(&self) -> Vector<T> {
let mut ans = Vec::with_capacity(self.length);
for i in &self.data {
ans.push(i.exp());
}
Vector::from(ans)
}
}
impl<T: Num> Add<Vector<T>> for Vector<T> {
type Output = Vector<T>;
fn add(self, rhs: Vector<T>) -> Self::Output {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
let mut vec = vec![T::default(); self.length];
for i in 0..self.length {
vec[i] = self[i] + rhs[i];
}
Vector::from(vec)
}
}
impl<T: Num> Add<&Vector<T>> for Vector<T> {
type Output = Vector<T>;
fn add(self, rhs: &Vector<T>) -> Self::Output {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
let mut vec = vec![T::default(); self.length];
for i in 0..self.length {
vec[i] = self[i] + rhs[i];
}
Vector::from(vec)
}
}
impl<T: Num> AddAssign<Vector<T>> for Vector<T> {
fn add_assign(&mut self, rhs: Vector<T>) {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
for i in 0..self.length {
self[i] += rhs[i];
}
}
}
impl<T: Num> AddAssign<&Vector<T>> for Vector<T> {
fn add_assign(&mut self, rhs: &Vector<T>) {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
for i in 0..self.length {
self[i] += rhs[i];
}
}
}
impl<T: Num> Add<T> for Vector<T> {
type Output = Vector<T>;
fn add(self, rhs: T) -> Self::Output {
let mut vec = vec![T::default(); self.length];
for i in 0..self.length {
vec[i] = self[i] + rhs;
}
Vector::from(vec)
}
}
impl<T: Num> AddAssign<T> for Vector<T> {
fn add_assign(&mut self, rhs: T) {
for i in 0..self.length {
self[i] += rhs;
}
}
}
impl<T: Num> Sub<Vector<T>> for Vector<T> {
type Output = Vector<T>;
fn sub(self, rhs: Vector<T>) -> Self::Output {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
let mut vec = vec![T::default(); self.length];
for i in 0..self.length {
vec[i] = self[i] - rhs[i];
}
Vector::from(vec)
}
}
impl<T: Num> Sub<&Vector<T>> for Vector<T> {
type Output = Vector<T>;
fn sub(self, rhs: &Vector<T>) -> Self::Output {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
let mut vec = vec![T::default(); self.length];
for i in 0..self.length {
vec[i] = self[i] - rhs[i];
}
Vector::from(vec)
}
}
impl<T: Num> SubAssign<Vector<T>> for Vector<T> {
fn sub_assign(&mut self, rhs: Self) {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
for i in 0..self.length {
self[i] -= rhs[i];
}
}
}
impl<T: Num> SubAssign<&Vector<T>> for Vector<T> {
fn sub_assign(&mut self, rhs: &Vector<T>) {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
for i in 0..self.length {
self[i] -= rhs[i];
}
}
}
impl<T: Num> Sub<T> for Vector<T> {
type Output = Vector<T>;
fn sub(self, rhs: T) -> Self::Output {
let mut vec = vec![T::default(); self.length];
for i in 0..self.length {
vec[i] = self[i] - rhs;
}
Vector::from(vec)
}
}
impl<T: Num> SubAssign<T> for Vector<T> {
fn sub_assign(&mut self, rhs: T) {
for i in 0..self.length {
self[i] -= rhs;
}
}
}
impl<T: Num> Mul<Vector<T>> for Vector<T> {
type Output = Vector<T>;
fn mul(self, rhs: Self) -> Self::Output {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
let mut vec = vec![T::default(); self.length];
for i in 0..self.length {
vec[i] = self[i] * rhs[i];
}
Vector::from(vec)
}
}
impl<T: Num> Mul<&Vector<T>> for Vector<T> {
type Output = Vector<T>;
fn mul(self, rhs: &Vector<T>) -> Self::Output {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
let mut vec = vec![T::default(); self.length];
for i in 0..self.length {
vec[i] = self[i] * rhs[i];
}
Vector::from(vec)
}
}
impl<T: Num> MulAssign<Vector<T>> for Vector<T> {
fn mul_assign(&mut self, rhs: Vector<T>) {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
for i in 0..self.length {
self[i] = self[i] * rhs[i];
}
}
}
impl<T: Num> MulAssign<&Vector<T>> for Vector<T> {
fn mul_assign(&mut self, rhs: &Vector<T>) {
if self.length != rhs.length {
panic!("!!!Different size of vectors!!!")
}
for i in 0..self.length {
self[i] = self[i] * rhs[i];
}
}
}
impl<T: Num> Mul<T> for Vector<T> {
type Output = Vector<T>;
fn mul(self, rhs: T) -> Self::Output {
let mut vec = vec![T::default(); self.length];
for i in 0..self.length {
vec[i] = self[i] * rhs;
}
Vector::from(vec)
}
}
impl<T: Num> MulAssign<T> for Vector<T> {
fn mul_assign(&mut self, rhs: T) {
for i in 0..self.length {
self[i] = self[i] * rhs;
}
}
}
macro_rules! impl_mul_for_types_vec {
($($type:ty),*) => {
$(
impl Mul<Vector<$type>> for $type {
type Output = Vector<$type>;
fn mul(self, rhs: Vector<$type>) -> Vector<$type> {
rhs * self
}
}
)*
};
}
impl_mul_for_types_vec!(i16, i32, i64, i128, f32, f64);
impl<T: Num> Into<Vec<T>> for Vector<T> {
fn into(self) -> Vec<T> {
self.data.clone().to_vec()
}
}
impl<T: Num> From<Vec<T>> for Vector<T> {
fn from(value: Vec<T>) -> Self {
Self {
data: value.clone(),
length: value.len(),
}
}
}
impl<T: Num> From<Matrix<T>> for Vector<T> {
fn from(value: Matrix<T>) -> Self {
if value.rows != 1 {
panic!("!!!Matrix rows must be equals 1 not {}!!!", value.rows)
}
Self {
data: value.data,
length: value.cols,
}
}
}
impl<T: Num> From<Tensor<T>> for Vector<T> {
fn from(value: Tensor<T>) -> Self {
if value.shape.len() != 1 {
panic!("Shape size must be 1")
}
Vector::from(value.data)
}
}
impl<T: Num> Display for Vector<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let string = self
.data
.iter()
.map(|x| format!("{}", x))
.collect::<Vec<_>>()
.join(" ");
write!(f, "{{{}}}", string)
}
}
impl<T: Num> Iterator for Vector<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.data.pop()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn map_test() {
let a = vector![1.0, 2.0, 3.0];
println!("{}", a.map_vec(|x| x + 1.0));
}
#[test]
fn range() {
let a = Vector::range(1.0, 4.0, 2.0).unwrap();
println!("{a}");
}
#[test]
fn macros_test() {
let a = vector![1, 2, 3];
let b = Vector::from(vec![1, 2, 3]);
assert_eq!(a, b)
}
#[test]
fn display_test() {
let a = Vector::from_num(-1, 3);
let b = Vector::from(vec![-1, -1, -1]);
assert_eq!(a, b);
}
#[test]
fn another_task() {
let a = vector![-3.0 + 7.0, 3.0 - 6.0];
let b = vector![2.0 - 2.0, 5.0 - 1.0];
let c = vector![-4.0 - 4.0, -2.0 + 4.0];
let d = a + b + c;
assert_eq!(5.0, d.length());
}
#[test]
fn from_number() {
let a = Vector::from_num(1, 2);
assert_eq!(Vector::from(vec![1, 1]), a);
}
#[test]
fn resize() {
let a = Vector::from_num(1, 3);
let a = a.resize(2);
assert_eq!(Vector::from(vec![1, 1]), a);
}
#[test]
fn scalar() {
let a = vec![1, 2];
let b = vec![2, 1];
let a = Vector::from(a);
let b = Vector::from(b);
assert_eq!(a.scalar(&b), 4);
}
#[test]
fn scalar_dif_size() {
let a = vec![1, 2, 1];
let b = vec![2, 1];
let a = Vector::from(a);
let b = Vector::from(b);
assert_eq!(a.scalar(&b), 4);
}
#[test]
fn len_vector() {
let a = Vector::from(vec![4.0, 3.0]);
assert_eq!(a.length(), 5f64);
}
#[test]
fn add_vectors() {
let a = vec![1, 2, 1];
let b = vec![2, 1, 0];
let a = Vector::from(a);
let b = Vector::from(b);
let c = a + b;
assert_eq!(Vector::from(vec![3, 3, 1]), c);
}
#[test]
fn add_to_vector() {
let a = vec![1, 2, 1];
let b = vec![2, 1, 0];
let mut a = Vector::from(a);
let b = Vector::from(b);
a += b;
assert_eq!(Vector::from(vec![3, 3, 1]), a);
}
#[test]
fn sub_to_vector() {
let mut a = Vector::from_num(1, 1);
let b = Vector::from_num(1, 1);
a -= b;
a += 1;
assert_eq!(Vector::from(vec![1]), a);
}
#[test]
fn mul_to_vector() {
let a = vec![1, 2, 1];
let b = vec![2, 1, 0];
let mut a = Vector::from(a);
let b = Vector::from(b);
a = a * b;
a = a * 0;
assert_eq!(Vector::from(vec![0, 0, 0]), a);
}
#[test]
fn exp_test() {
let a = vector![1.0, 0.0];
assert_eq!(vector![std::f64::consts::E, 1.0], a.exp());
}
#[test]
fn abs_sum() {
let a = vector![-3.0, 5.0, 7.0];
assert_eq!(15.0, a.abs_sum());
}
#[test]
fn add_many_times() {
let mut a = vector![1.0, 1.0, 1.0];
let mut b = vector![0.0, 0.0, 0.0];
b += 1.;
a += &b;
a = a + &b;
assert_eq!(vector![3.0, 3.0, 3.0], a);
}
#[test]
fn sub_many_times() {
let mut a = vector![1.0, 1.0, 1.0];
let mut b = vector![2.0, 2.0, 2.0];
a += 1.;
b -= 1.;
a -= &b;
a = a - b;
assert_eq!(vector![0.0, 0.0, 0.0], a);
}
#[test]
fn mul_many_times() {
let mut a = Vector::from_num(1.0, 3);
let mut b = Vector::from_num(0.5, 3);
b *= 4.0;
a *= &b;
a = a * &b;
assert_eq!(Vector::from_num(4.0, 3), a);
}
#[test]
fn linspace_test() {
let a = Vector::linspace(0.0, 10.0, 11, true);
println!("{a}");
}
#[test]
fn table_test() {
let a = vector![1.0, 2.0 ,3.0];
let b = vector![10.0, 20.0];
let m = a.table(&b, |x, y| x * y);
println!("{m}");
}
#[test]
fn mandeltbrot_set() {
let y = Vector::linspace(-2.0, 1.0, 1000, true);
let x = y.clone();
let mandelbrot_mx = y.table(&x, |y, x| {
let mut zx:f64 = 0.0;
let mut zy:f64 = 0.0;
for _ in 0..255 {
let xtemp = zx * zx * zx - 3.0 * zx * zy * zy + x;
zy = 3.0 * zx * zx * zy - zy * zy * zy + y;
zx = xtemp;
if zx > 10.0 || zy > 10.0 || zx < -10.0 || zy < -10.0 {
return (zx * zy).abs().min(1.0); }
}
1.0
});
for i in 0..mandelbrot_mx.rows {
for j in 0..mandelbrot_mx.cols {
if mandelbrot_mx[[i, j]] == 1.0{
print!("#");
} else {
print!(" ");
}
}
println!();
}
}
}