Skip to content

Commit 73def89

Browse files
committed
update: 完成 20 题
Signed-off-by: YdrMaster <[email protected]>
1 parent 257cc30 commit 73def89

File tree

6 files changed

+183
-28
lines changed

6 files changed

+183
-28
lines changed
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include "../exercise.h"
2+
3+
// READ: 函数模板 <https://zh.cppreference.com/w/cpp/language/function_template>
4+
// TODO: 将这个函数模板化
5+
int plus(int a, int b) {
6+
return a + b;
7+
}
8+
9+
// ---- 不要修改以下代码 ----
10+
int main(int argc, char **argv) {
11+
ASSERT(plus(1, 2) == 3, "plus two int");
12+
ASSERT(plus(1u, 2u) == 3u, "plus two unsigned int");
13+
ASSERT(plus(1.f, 2.f) == 3.f, "plus two float");
14+
ASSERT(plus(1.0, 2.0) == 3.0, "plus two double");
15+
return 0;
16+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include "../exercise.h"
2+
#include <cmath>
3+
4+
enum class DataType {
5+
Float,
6+
Double,
7+
};
8+
9+
/// @brief Tagged union 即标签化联合体,是联合体的一种常见应用。
10+
/// Rust enum 在实现上就是标签化联合体。
11+
struct TaggedUnion {
12+
DataType type;
13+
// NOTICE: struct/union 可以相互任意嵌套。
14+
union {
15+
float f;
16+
double d;
17+
};
18+
};
19+
20+
// TODO: 将这个函数模板化用于 sigmoid_dyn
21+
float sigmoid(float x) {
22+
return 1 / (1 + std::exp(-x));
23+
}
24+
25+
TaggedUnion sigmoid_dyn(TaggedUnion x) {
26+
TaggedUnion ans{x.type};
27+
// TODO: 根据 type 调用 sigmoid
28+
return ans;
29+
}
30+
31+
// ---- 不要修改以下代码 ----
32+
int main(int argc, char **argv) {
33+
TaggedUnion xf{DataType::Float};
34+
xf.f = 5.f;
35+
auto yf = sigmoid_dyn(xf);
36+
ASSERT(yf.type == DataType::Float, "type mismatch");
37+
ASSERT(yf.f == 1 / (1 + exp(-5.f)), "sigmoid float");
38+
39+
TaggedUnion xd{DataType::Double};
40+
xd.d = 5.0;
41+
auto yd = sigmoid_dyn(xd);
42+
ASSERT(yd.type == DataType::Double, "type mismatch");
43+
ASSERT(yd.d == 1 / (1 + exp(-5.0)), "sigmoid double");
44+
return 0;
45+
}

exercises/20_class_template/main.cpp

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#include "../exercise.h"
2+
3+
// READ: 类模板 <https://zh.cppreference.com/w/cpp/language/class_template>
4+
5+
template<class T>
6+
struct Tensor4D {
7+
unsigned int shape[4];
8+
T *data;
9+
10+
Tensor4D(unsigned int const shape_[4], T const *data_) {
11+
unsigned int size = 1;
12+
// TODO: 填入正确的 shape 并计算 size
13+
data = new T[size];
14+
std::memcpy(data, data_, size * sizeof(T));
15+
}
16+
~Tensor4D() {
17+
delete[] data;
18+
}
19+
20+
// 为了保持简单,禁止复制和移动
21+
Tensor4D(Tensor4D const &) = delete;
22+
Tensor4D(Tensor4D &&) noexcept = delete;
23+
24+
// 这个加法需要支持“单向广播”。
25+
// 具体来说,`others` 可以具有与 `this` 不同的形状,形状不同的维度长度必须为 1。
26+
// `others` 长度为 1 但 `this` 长度不为 1 的维度将发生广播计算。
27+
// 例如,`this` 形状为 `[1, 2, 3, 4]`,`others` 形状为 `[1, 2, 1, 4]`,
28+
// 则 `this` 与 `others` 相加时,3 个形状为 `[1, 2, 1, 4]` 的子张量各自与 `others` 对应项相加。
29+
Tensor4D &operator+=(Tensor4D const &others) {
30+
// TODO: 实现单向广播的加法
31+
return *this;
32+
}
33+
};
34+
35+
// ---- 不要修改以下代码 ----
36+
int main(int argc, char **argv) {
37+
{
38+
unsigned int shape[]{1, 2, 3, 4};
39+
// clang-format off
40+
int data[]{
41+
1, 2, 3, 4,
42+
5, 6, 7, 8,
43+
9, 10, 11, 12,
44+
45+
13, 14, 15, 16,
46+
17, 18, 19, 20,
47+
21, 22, 23, 24};
48+
// clang-format on
49+
auto t0 = Tensor4D(shape, data);
50+
auto t1 = Tensor4D(shape, data);
51+
t0 += t1;
52+
for (unsigned int i = 0; i < sizeof(data) / sizeof(int); i++) {
53+
ASSERT(t0.data[i] == data[i] * 2, "Tensor doubled by plus its self.");
54+
}
55+
}
56+
{
57+
unsigned int s0[]{1, 2, 3, 4};
58+
// clang-format off
59+
float d0[]{
60+
1, 1, 1, 1,
61+
2, 2, 2, 2,
62+
3, 3, 3, 3,
63+
64+
4, 4, 4, 4,
65+
5, 5, 5, 5,
66+
6, 6, 6, 6};
67+
// clang-format on
68+
unsigned int s1[]{1, 2, 3, 1};
69+
// clang-format off
70+
float d1[]{
71+
6,
72+
5,
73+
4,
74+
75+
3,
76+
2,
77+
1};
78+
// clang-format on
79+
80+
auto t0 = Tensor4D(s0, d0);
81+
auto t1 = Tensor4D(s1, d1);
82+
t0 += t1;
83+
for (unsigned int i = 0; i < sizeof(d0) / sizeof(int); i++) {
84+
ASSERT(t0.data[i] == 7.f, "Every element of t0 should be 7 after adding t1 to it.");
85+
}
86+
}
87+
{
88+
unsigned int s0[]{1, 2, 3, 4};
89+
// clang-format off
90+
double d0[]{
91+
1, 2, 3, 4,
92+
5, 6, 7, 8,
93+
9, 10, 11, 12,
94+
95+
13, 14, 15, 16,
96+
17, 18, 19, 20,
97+
21, 22, 23, 24};
98+
// clang-format on
99+
unsigned int s1[]{1, 1, 1, 1};
100+
double d1[]{1};
101+
102+
auto t0 = Tensor4D(s0, d0);
103+
auto t1 = Tensor4D(s1, d1);
104+
t0 += t1;
105+
for (unsigned int i = 0; i < sizeof(d0) / sizeof(int); i++) {
106+
ASSERT(t0.data[i] == t0.data[i] + 1, "Every element of t0 should be incremented by 1 after adding t1 to it.");
107+
}
108+
}
109+
}

exercises/exercise.h

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,13 @@
33

44
#include <iostream>
55

6-
template<class T>
7-
struct Colorful {
8-
int color;
9-
T value;
10-
};
11-
12-
template<class T>
13-
inline std::ostream &operator<<(std::ostream &os, Colorful<T> const &cf) {
14-
return os << "\x1b[" << cf.color << 'm' << cf.value << "\x1b[0m";
15-
}
16-
17-
#define COLORFUL(VALUE, NAME) \
18-
template<class T> \
19-
inline Colorful<T> NAME(T &&val) { \
20-
return {(VALUE), std::forward<T>(val)}; \
21-
}
22-
23-
COLORFUL(31, red)
24-
COLORFUL(32, green)
25-
COLORFUL(33, yellow)
26-
COLORFUL(34, blue)
27-
28-
#undef COLORFUL
29-
306
#define ASSERT(COND, MSG) \
317
if (!(COND)) { \
32-
std::cerr << red("Assertion failed at line #") << red(__LINE__) << red(": ") << std::endl \
8+
std::cerr << "\x1b[31mAssertion failed at line #" << __LINE__ << ": \x1b[0m" << std::endl \
339
<< std::endl \
3410
<< #COND << std::endl \
3511
<< std::endl \
36-
<< green("Message:") << std::endl \
12+
<< "\x1b[34mMessage:\x1b[0m" << std::endl \
3713
<< std::endl \
3814
<< MSG << std::endl \
3915
<< std::endl; \

exercises/xmake.lua

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,13 @@ target("exercise16")
5858
target("exercise17")
5959
add_files("17_class_virtual_destruct/main.cpp")
6060

61-
-- TODO: template; array; vector; deque; map; transform; accumulate; fs; thread; mutex;
61+
target("exercise18")
62+
add_files("18_function_template/main.cpp")
63+
64+
target("exercise19")
65+
add_files("19_runtime_datatype/main.cpp")
66+
67+
target("exercise20")
68+
add_files("20_class_template/main.cpp")
69+
70+
-- TODO: array; vector; deque; map; forward_list; transform; accumulate; fs; thread; mutex;

learn/summary.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include <sstream>
77
#include <vector>
88

9-
constexpr auto MAX_EXERCISE = 17;
9+
constexpr auto MAX_EXERCISE = 20;
1010

1111
int main(int argc, char **argv) {
1212
if (argc == 1) {

0 commit comments

Comments
 (0)