1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*!
 * `map` for heterogenous structures. Internal Rustmex tooling.
 *
 * This module defines the Mappable family of traits. These provide some mapping
 * function, taking a closure, which is applied to every part of some object. These are
 * mostly used on [`Complex<T>`], since it is used by NDarray as a general container type.
 */

use num_complex::Complex;

use std::ops::{Deref, DerefMut};

/**
 * A single value wrapper for T, as a counterpart to the paired T in [`Complex<T>`]. This
 * allows the same code for the [`Mappable`] trait family to be used regardless of
 * whether a [`Complex<T>`] or a [`Real<T>`] is used.
 */
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq)]
#[repr(transparent)]
pub struct Real<T>(pub T);

impl<T> Deref for Real<T> {
	type Target = T;
	fn deref(&self) -> &Self::Target {
		&self.0
	}

}

impl<T> DerefMut for Real<T> {
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.0
	}

}

impl<T> Real<T> {
	/**
	 * Convert a boxed slice of T's into a boxed slice of [`Real<T>`].
	 */
	pub fn from_boxed_slice(s: Box<[T]>) -> Box<[Real<T>]> {
		// SAFETY: Since the ABI of T is the same as that of Real<T>, it is safe
		// to transmute from T to Real<T>.
		unsafe { std::mem::transmute(s) }
	}
}

/**
 * Convert some object into another object via some shared behaviour for each of its
 * parts.
 */
pub trait Mappable<A, B> {
	/// The return type. Can be Self, but with a modified inner type, or something
	/// entirely different
	type Target;

	/// Perform the conversion by value
	fn map<F>(self, f: F) -> Self::Target where F: Fn(A) -> B;
}


impl<A, B> Mappable<A, B> for Complex<A> {
	type Target = Complex<B>;
	fn map<F>(self, f: F) -> Self::Target where F: Fn(A) -> B {
		Self::Target {
			re: f(self.re),
			im: f(self.im)
		}
	}
}

impl<A, B> Mappable<A, B> for Real<A> {
	type Target = Real<B>;
	fn map<F>(self, f: F) -> Self::Target where F: Fn(A) -> B {
		Real(f(self.0))
	}
}

/**
 * Mutate some object via some shared behaviour applied to each of its parts.
 */
pub trait MutMappable<T> {
	/// Perform the mutation
	fn map_mut<F>(&mut self, f: F) where F: Fn(&mut T);
}

impl<T> MutMappable<T> for Complex<T> {
	fn map_mut<F>(&mut self, f: F) where F: Fn(&mut T) {
		f(&mut self.re);
		f(&mut self.im);
	}
}

impl<T> MutMappable<T> for Real<T> {
	fn map_mut<F>(&mut self, f: F) where F: Fn(&mut T) {
		f(&mut self.0);
	}
}

/**
 * Derive a new type through applying some function to each of its constituent parts by
 * reference.
 */
pub trait RefMappable<A, B> {
	type Target;
	/// Perform the derivation
	fn map_ref<F>(&self, f: F) -> Self::Target where F: Fn(&A) -> B;
}

impl<A, B> RefMappable<A, B> for Complex<A> {
	type Target = Complex<B>;

	fn map_ref<F>(&self, f: F) -> Self::Target where F: Fn(&A) -> B {
		Self::Target {
			re: f(&self.re),
			im: f(&self.im)
		}
	}
}

impl<A, B> RefMappable<A, B> for Real<A> {
	type Target = Real<B>;

	fn map_ref<F>(&self, f: F) -> Self::Target where F: Fn(&A) -> B {
		Real(f(&self.0))
	}
}

/**
 * Initialise a homogenous struct by applying some function for each field
 */
pub trait Init<T> {
	fn init<F>(f: F) -> Self where F: Fn() -> T;
}

impl<T> Init<T> for Complex<T> {
	fn init<F>(f: F) -> Self where F: Fn() -> T {
		Complex {
			re: f(),
			im: f()
		}
	}
}

impl<T> Init<T> for Real<T> {
	fn init<F>(f: F) -> Self where F: Fn() -> T {
		Self(f())
	}
}

pub trait InitValue<T> {
	fn init_value(v: T) -> Self;
}

impl<T> InitValue<T> for Complex<T> where T: Clone {
	fn init_value(v: T) -> Self {
		Complex {
			re: v.clone(),
			im: v,
		}
	}
}

impl<T> InitValue<T> for Real<T> {
	fn init_value(v: T) -> Self {
		Real(v)
	}
}

/**
 * Condense a homogenous struct through a function, taking all of its fields, and
 * producing one value.
 */
pub trait Merge<A, B> {
	fn merge<F>(self, f: F) -> B where F: Fn(&[A]) -> B;
}

impl<A, B> Merge<A, B> for Complex<A> {
	fn merge<F>(self, f:F) -> B where F: Fn(&[A]) -> B {
		f(&[self.re, self.im])
	}
}

impl<A, B> Merge<A, B> for Real<A> {
	fn merge<F>(self, f:F) -> B where F: Fn(&[A]) -> B {
		f(&[self.0])
	}
}