Skip to content

Commit

Permalink
update: 完成 20 题
Browse files Browse the repository at this point in the history
Signed-off-by: YdrMaster <[email protected]>
  • Loading branch information
YdrMaster committed Jul 12, 2024
1 parent 257cc30 commit 73def89
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 28 deletions.
16 changes: 16 additions & 0 deletions exercises/18_function_template/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include "../exercise.h"

// READ: 函数模板 <https://zh.cppreference.com/w/cpp/language/function_template>
// TODO: 将这个函数模板化
int plus(int a, int b) {
return a + b;
}

// ---- 不要修改以下代码 ----
int main(int argc, char **argv) {
ASSERT(plus(1, 2) == 3, "plus two int");
ASSERT(plus(1u, 2u) == 3u, "plus two unsigned int");
ASSERT(plus(1.f, 2.f) == 3.f, "plus two float");
ASSERT(plus(1.0, 2.0) == 3.0, "plus two double");
return 0;
}
45 changes: 45 additions & 0 deletions exercises/19_runtime_datatype/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "../exercise.h"
#include <cmath>

enum class DataType {
Float,
Double,
};

/// @brief Tagged union 即标签化联合体,是联合体的一种常见应用。
/// Rust enum 在实现上就是标签化联合体。
struct TaggedUnion {
DataType type;
// NOTICE: struct/union 可以相互任意嵌套。
union {
float f;
double d;
};
};

// TODO: 将这个函数模板化用于 sigmoid_dyn
float sigmoid(float x) {
return 1 / (1 + std::exp(-x));
}

TaggedUnion sigmoid_dyn(TaggedUnion x) {
TaggedUnion ans{x.type};
// TODO: 根据 type 调用 sigmoid
return ans;
}

// ---- 不要修改以下代码 ----
int main(int argc, char **argv) {
TaggedUnion xf{DataType::Float};
xf.f = 5.f;
auto yf = sigmoid_dyn(xf);
ASSERT(yf.type == DataType::Float, "type mismatch");
ASSERT(yf.f == 1 / (1 + exp(-5.f)), "sigmoid float");

TaggedUnion xd{DataType::Double};
xd.d = 5.0;
auto yd = sigmoid_dyn(xd);
ASSERT(yd.type == DataType::Double, "type mismatch");
ASSERT(yd.d == 1 / (1 + exp(-5.0)), "sigmoid double");
return 0;
}
109 changes: 109 additions & 0 deletions exercises/20_class_template/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include "../exercise.h"

// READ: 类模板 <https://zh.cppreference.com/w/cpp/language/class_template>

template<class T>
struct Tensor4D {
unsigned int shape[4];
T *data;

Tensor4D(unsigned int const shape_[4], T const *data_) {
unsigned int size = 1;
// TODO: 填入正确的 shape 并计算 size
data = new T[size];
std::memcpy(data, data_, size * sizeof(T));
}
~Tensor4D() {
delete[] data;
}

// 为了保持简单,禁止复制和移动
Tensor4D(Tensor4D const &) = delete;
Tensor4D(Tensor4D &&) noexcept = delete;

// 这个加法需要支持“单向广播”。
// 具体来说,`others` 可以具有与 `this` 不同的形状,形状不同的维度长度必须为 1。
// `others` 长度为 1 但 `this` 长度不为 1 的维度将发生广播计算。
// 例如,`this` 形状为 `[1, 2, 3, 4]`,`others` 形状为 `[1, 2, 1, 4]`,
// 则 `this` 与 `others` 相加时,3 个形状为 `[1, 2, 1, 4]` 的子张量各自与 `others` 对应项相加。
Tensor4D &operator+=(Tensor4D const &others) {
// TODO: 实现单向广播的加法
return *this;
}
};

// ---- 不要修改以下代码 ----
int main(int argc, char **argv) {
{
unsigned int shape[]{1, 2, 3, 4};
// clang-format off
int data[]{
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,

13, 14, 15, 16,
17, 18, 19, 20,
21, 22, 23, 24};
// clang-format on
auto t0 = Tensor4D(shape, data);
auto t1 = Tensor4D(shape, data);
t0 += t1;
for (unsigned int i = 0; i < sizeof(data) / sizeof(int); i++) {
ASSERT(t0.data[i] == data[i] * 2, "Tensor doubled by plus its self.");
}
}
{
unsigned int s0[]{1, 2, 3, 4};
// clang-format off
float d0[]{
1, 1, 1, 1,
2, 2, 2, 2,
3, 3, 3, 3,

4, 4, 4, 4,
5, 5, 5, 5,
6, 6, 6, 6};
// clang-format on
unsigned int s1[]{1, 2, 3, 1};
// clang-format off
float d1[]{
6,
5,
4,

3,
2,
1};
// clang-format on

auto t0 = Tensor4D(s0, d0);
auto t1 = Tensor4D(s1, d1);
t0 += t1;
for (unsigned int i = 0; i < sizeof(d0) / sizeof(int); i++) {
ASSERT(t0.data[i] == 7.f, "Every element of t0 should be 7 after adding t1 to it.");
}
}
{
unsigned int s0[]{1, 2, 3, 4};
// clang-format off
double d0[]{
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,

13, 14, 15, 16,
17, 18, 19, 20,
21, 22, 23, 24};
// clang-format on
unsigned int s1[]{1, 1, 1, 1};
double d1[]{1};

auto t0 = Tensor4D(s0, d0);
auto t1 = Tensor4D(s1, d1);
t0 += t1;
for (unsigned int i = 0; i < sizeof(d0) / sizeof(int); i++) {
ASSERT(t0.data[i] == t0.data[i] + 1, "Every element of t0 should be incremented by 1 after adding t1 to it.");
}
}
}
28 changes: 2 additions & 26 deletions exercises/exercise.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,13 @@

#include <iostream>

template<class T>
struct Colorful {
int color;
T value;
};

template<class T>
inline std::ostream &operator<<(std::ostream &os, Colorful<T> const &cf) {
return os << "\x1b[" << cf.color << 'm' << cf.value << "\x1b[0m";
}

#define COLORFUL(VALUE, NAME) \
template<class T> \
inline Colorful<T> NAME(T &&val) { \
return {(VALUE), std::forward<T>(val)}; \
}

COLORFUL(31, red)
COLORFUL(32, green)
COLORFUL(33, yellow)
COLORFUL(34, blue)

#undef COLORFUL

#define ASSERT(COND, MSG) \
if (!(COND)) { \
std::cerr << red("Assertion failed at line #") << red(__LINE__) << red(": ") << std::endl \
std::cerr << "\x1b[31mAssertion failed at line #" << __LINE__ << ": \x1b[0m" << std::endl \
<< std::endl \
<< #COND << std::endl \
<< std::endl \
<< green("Message:") << std::endl \
<< "\x1b[34mMessage:\x1b[0m" << std::endl \
<< std::endl \
<< MSG << std::endl \
<< std::endl; \
Expand Down
11 changes: 10 additions & 1 deletion exercises/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,13 @@ target("exercise16")
target("exercise17")
add_files("17_class_virtual_destruct/main.cpp")

-- TODO: template; array; vector; deque; map; transform; accumulate; fs; thread; mutex;
target("exercise18")
add_files("18_function_template/main.cpp")

target("exercise19")
add_files("19_runtime_datatype/main.cpp")

target("exercise20")
add_files("20_class_template/main.cpp")

-- TODO: array; vector; deque; map; forward_list; transform; accumulate; fs; thread; mutex;
2 changes: 1 addition & 1 deletion learn/summary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <sstream>
#include <vector>

constexpr auto MAX_EXERCISE = 17;
constexpr auto MAX_EXERCISE = 20;

int main(int argc, char **argv) {
if (argc == 1) {
Expand Down

0 comments on commit 73def89

Please sign in to comment.