1use crate::{cpu::scalar_apply, Matrix};
2use custos::{impl_stack, number::Number, CDatatype, Device, MainMemory, Shape};
3
4#[cfg(feature = "cpu")]
5use custos::CPU;
6
7#[cfg(feature = "stack")]
8use custos::Stack;
9
10#[cfg(feature = "opencl")]
11use crate::opencl::cl_scalar_op_mat;
12#[cfg(feature = "opencl")]
13use custos::OpenCL;
14
15#[cfg(feature = "cuda")]
16use crate::cuda::cu_scalar_op;
17#[cfg(feature = "cuda")]
18use custos::CUDA;
19
20impl<'a, T, D, S> Matrix<'a, T, D, S>
21where
22 D: AdditionalOps<T, S>,
23 S: Shape,
24{
25 #[inline]
26 pub fn adds(&self, rhs: T) -> Self {
27 self.device().adds(self, rhs)
28 }
29
30 #[inline]
31 pub fn subs(&self, rhs: T) -> Self {
32 self.device().subs(self, rhs)
33 }
34
35 #[inline]
36 pub fn muls(&self, rhs: T) -> Self {
37 self.device().muls(self, rhs)
38 }
39
40 #[inline]
41 pub fn divs(&self, rhs: T) -> Self {
42 self.device().divs(self, rhs)
43 }
44}
45
46pub trait AdditionalOps<T, S: Shape = (), D: Device = Self>: Device {
47 fn adds(&self, lhs: &Matrix<T, D, S>, rhs: T) -> Matrix<T, Self, S>;
48 fn subs(&self, lhs: &Matrix<T, D, S>, rhs: T) -> Matrix<T, Self, S>;
49 fn muls(&self, lhs: &Matrix<T, D, S>, rhs: T) -> Matrix<T, Self, S>;
50 fn divs(&self, lhs: &Matrix<T, D, S>, rhs: T) -> Matrix<T, Self, S>;
51}
52
53#[cfg(feature = "cuda")]
54impl<T: CDatatype> AdditionalOps<T> for CUDA {
55 #[inline]
56 fn adds(&self, lhs: &Matrix<T, CUDA>, rhs: T) -> Matrix<T, CUDA> {
57 (cu_scalar_op(self, lhs, rhs, "+").unwrap(), lhs.dims()).into()
58 }
59
60 #[inline]
61 fn muls(&self, lhs: &Matrix<T, CUDA>, rhs: T) -> Matrix<T, CUDA> {
62 (cu_scalar_op(self, lhs, rhs, "*").unwrap(), lhs.dims()).into()
63 }
64
65 #[inline]
66 fn divs(&self, lhs: &Matrix<T, CUDA>, rhs: T) -> Matrix<T, CUDA> {
67 (cu_scalar_op(self, lhs, rhs, "/").unwrap(), lhs.dims()).into()
68 }
69
70 fn subs(&self, lhs: &Matrix<T, Self>, rhs: T) -> Matrix<T, Self, ()> {
71 (cu_scalar_op(self, lhs, rhs, "-").unwrap(), lhs.dims()).into()
72 }
73}
74
75#[cfg(feature = "opencl")]
76impl<T: CDatatype> AdditionalOps<T> for OpenCL {
77 #[inline]
78 fn adds(&self, lhs: &Matrix<T, Self>, rhs: T) -> Matrix<T, Self> {
79 cl_scalar_op_mat(self, lhs, rhs, "+").unwrap()
80 }
81
82 #[inline]
83 fn subs(&self, lhs: &Matrix<T, Self, ()>, rhs: T) -> Matrix<T, Self, ()> {
84 cl_scalar_op_mat(self, lhs, rhs, "-").unwrap()
85 }
86
87 #[inline]
88 fn muls(&self, lhs: &Matrix<T, Self>, rhs: T) -> Matrix<T, Self> {
89 cl_scalar_op_mat(self, lhs, rhs, "*").unwrap()
90 }
91
92 #[inline]
93 fn divs(&self, lhs: &Matrix<T, Self>, rhs: T) -> Matrix<T, Self> {
94 cl_scalar_op_mat(self, lhs, rhs, "/").unwrap()
95 }
96}
97
98#[impl_stack]
99impl<T: Number, D: MainMemory, S: Shape> AdditionalOps<T, S, D> for CPU {
100 #[inline]
101 fn adds(&self, lhs: &Matrix<T, D, S>, rhs: T) -> Matrix<T, Self, S> {
102 scalar_apply(self, lhs, rhs, |c, a, b| *c = a + b)
103 }
104
105 #[inline]
106 fn subs(&self, lhs: &Matrix<T, D, S>, rhs: T) -> Matrix<T, Self, S> {
107 scalar_apply(self, lhs, rhs, |c, a, b| *c = a - b)
108 }
109
110 #[inline]
111 fn muls(&self, lhs: &Matrix<T, D, S>, rhs: T) -> Matrix<T, Self, S> {
112 scalar_apply(self, lhs, rhs, |c, a, b| *c = a * b)
113 }
114
115 #[inline]
116 fn divs(&self, lhs: &Matrix<T, D, S>, rhs: T) -> Matrix<T, Self, S> {
117 scalar_apply(self, lhs, rhs, |c, a, b| *c = a / b)
118 }
119}