1+ #include "../../include/cten.h"
2+ #include "../test_utils.h"
3+ #include "../csv_reporter.h"
4+ #include "../test_config.h"
5+ #include <stdio.h>
6+
7+ void test_abs_backward () {
8+ const char * op_name = "abs_backward" ;
9+ PoolId pool_id = 0 ;
10+ cten_begin_malloc (pool_id );
11+
12+ // Test Case 1: Simple backward
13+ {
14+ const char * tc_name = "Simple_backward" ;
15+ // Sub-test 1: Scalar backward
16+ {
17+ TensorShape s_shape = {1 };
18+ float d1 [] = {-5.0f };
19+ float exp_grad [] = {-1.0f };
20+
21+ Tensor t1 = create_test_tensor (s_shape , d1 , true);
22+ Tensor z = Tensor_abs (t1 );
23+
24+ Tensor_backward (z , (Tensor ){0 });
25+
26+ Tensor expected_grad = create_test_tensor (s_shape , exp_grad , false);
27+ compare_tensors (& t1 .node -> grad , & expected_grad , op_name , tc_name , 1 , TEST_FLOAT_TOLERANCE );
28+ }
29+
30+ // Sub-test 2: Vector with mixed values
31+ {
32+ TensorShape v_shape = {5 };
33+ float d1 [] = {10.0f , -2.0f , 0.0f , 5.5f , -0.1f };
34+ float exp_grad [] = {1.0f , -1.0f , 0.0f , 1.0f , -1.0f };
35+
36+ Tensor t1 = create_test_tensor (v_shape , d1 , true);
37+ Tensor z = Tensor_abs (t1 );
38+ Tensor l = Tensor_sum (z );
39+
40+ Tensor_backward (l , (Tensor ){0 });
41+
42+ Tensor expected_grad = create_test_tensor (v_shape , exp_grad , false);
43+ compare_tensors (& t1 .node -> grad , & expected_grad , op_name , tc_name , 2 , TEST_FLOAT_TOLERANCE );
44+ }
45+
46+ // Sub-test 3: Matrix backward
47+ {
48+ TensorShape m_shape = {2 , 2 };
49+ float d1 [] = {1.0f , -2.0f , 0.0f , -4.0f };
50+ float exp_grad [] = {1.0f , -1.0f , 0.0f , -1.0f };
51+
52+ Tensor t1 = create_test_tensor (m_shape , d1 , true);
53+ Tensor z = Tensor_abs (t1 );
54+ Tensor l = Tensor_sum (z );
55+
56+ Tensor_backward (l , (Tensor ){0 });
57+
58+ Tensor expected_grad = create_test_tensor (m_shape , exp_grad , false);
59+ compare_tensors (& t1 .node -> grad , & expected_grad , op_name , tc_name , 3 , TEST_FLOAT_TOLERANCE );
60+ }
61+ }
62+
63+ // Test Case 2: Multi-dimensional Tensor backward
64+ {
65+ const char * tc_name = "Multidim_backward" ;
66+ TensorShape shape_3d = {2 , 2 , 2 };
67+ float data [] = {1.5f , -2.5f , 0.0f , -4.5f , 5.5f , 6.5f , -7.5f , -8.5f };
68+ float exp_grad [] = {1.0f , -1.0f , 0.0f , -1.0f , 1.0f , 1.0f , -1.0f , -1.0f };
69+
70+ Tensor t = create_test_tensor (shape_3d , data , true);
71+ Tensor z = Tensor_abs (t );
72+ Tensor l = Tensor_sum (z );
73+ Tensor_backward (l , (Tensor ){0 });
74+
75+ Tensor expected_grad = create_test_tensor (shape_3d , exp_grad , false);
76+ compare_tensors (& t .node -> grad , & expected_grad , op_name , tc_name , 1 , TEST_FLOAT_TOLERANCE );
77+ }
78+
79+
80+ // Test Case 3: Chained and Complex Graphs
81+ {
82+ const char * tc_name = "Chained_and_Complex_Graphs_backward" ;
83+ // Sub-test 1: z = abs(x) * w
84+ {
85+ TensorShape shape = {2 };
86+ float x_data [] = {-2.0f , 3.0f };
87+ float w_data [] = {5.0f , 10.0f };
88+ // z = abs(x)*w = {2, 3} * {5, 10} = {10, 30}
89+ // l = sum(z) = 40
90+ // dl/dx = (dl/dz) * (dz/dx) = {1, 1} * (w * sign(x)) = {5*(-1), 10*1} = {-5, 10}
91+ // dl/dw = (dl/dz) * (dz/dw) = {1, 1} * abs(x) = {2, 3}
92+ float exp_grad_x [] = {-5.0f , 10.0f };
93+ float exp_grad_w [] = {2.0f , 3.0f };
94+
95+ Tensor x = create_test_tensor (shape , x_data , true);
96+ Tensor w = create_test_tensor (shape , w_data , true);
97+
98+ Tensor abs_x = Tensor_abs (x );
99+ Tensor prod = Tensor_mul (abs_x , w );
100+ Tensor l = Tensor_sum (prod );
101+
102+ Tensor_backward (l , (Tensor ){0 });
103+
104+ Tensor expected_grad_x = create_test_tensor (shape , exp_grad_x , false);
105+ Tensor expected_grad_w = create_test_tensor (shape , exp_grad_w , false);
106+
107+ compare_tensors (& x .node -> grad , & expected_grad_x , op_name , tc_name , 1 , TEST_FLOAT_TOLERANCE );
108+ compare_tensors (& w .node -> grad , & expected_grad_w , op_name , tc_name , 2 , TEST_FLOAT_TOLERANCE );
109+ }
110+
111+ // Sub-test 2: z = abs(x * w)
112+ {
113+ TensorShape shape = {2 };
114+ float x_data [] = {-2.0f , 3.0f };
115+ float w_data [] = {5.0f , -1.0f };
116+ // y = x*w = {-10, -3}
117+ // z = abs(y) = {10, 3}
118+ // l = sum(z) = 13
119+ // dl/dx = (dl/dz)(dz/dy)(dy/dx) = {1,1} * sign(y) * w = {-1,-1} * {5,-1} = {-5, 1}
120+ // dl/dw = (dl/dz)(dz/dy)(dy/dw) = {1,1} * sign(y) * x = {-1,-1} * {-2,3} = {2, -3}
121+ float exp_grad_x [] = {-5.0f , 1.0f };
122+ float exp_grad_w [] = {2.0f , -3.0f };
123+
124+ Tensor x = create_test_tensor (shape , x_data , true);
125+ Tensor w = create_test_tensor (shape , w_data , true);
126+
127+ Tensor prod = Tensor_mul (x , w );
128+ Tensor abs_prod = Tensor_abs (prod );
129+ Tensor l = Tensor_sum (abs_prod );
130+
131+ Tensor_backward (l , (Tensor ){0 });
132+
133+ Tensor expected_grad_x = create_test_tensor (shape , exp_grad_x , false);
134+ Tensor expected_grad_w = create_test_tensor (shape , exp_grad_w , false);
135+
136+ compare_tensors (& x .node -> grad , & expected_grad_x , op_name , tc_name , 3 , TEST_FLOAT_TOLERANCE );
137+ compare_tensors (& w .node -> grad , & expected_grad_w , op_name , tc_name , 4 , TEST_FLOAT_TOLERANCE );
138+ }
139+ }
140+
141+ cten_free (pool_id );
142+ }
0 commit comments