Skip to content

Commit 34f3d9a

Browse files
add an art using pngwriter subproject
1 parent f667b1f commit 34f3d9a

File tree

13 files changed

+416
-0
lines changed

13 files changed

+416
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ set(CMAKE_BUILD_TYPE Release)
1616
add_subdirectory(basic)
1717
add_subdirectory(number_system)
1818
add_subdirectory(3D)
19+
add_subdirectory(image)

NN/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(FFN)

NN/FFN/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(basicFFN)

NN/FFN/basicFFN/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
include_directories(${CMAKE_CURRENT_SOURCE_DIR} include)
2+
3+
set(SRC ${CMAKE_CURRENT_SOURCE_DIR}/src)
4+
5+
add_executable(basicFFN ${SRC}/basicFFN.cxx)

NN/FFN/basicFFN/include/ffn.hxx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#pragma once
2+
3+
#include <type_traits>
4+
5+
#define INPUT_SIZE 1
6+
#define HIDDEN1_SIZE 256
7+
#define HIDDEN2_SIZE 256
8+
#define OUTPUT_SIZE 1
9+
10+
namespace NN {
11+
12+
template <typename FP,
13+
typename = std::enable_if_t<std::is_floating_point_v<FP>, FP>>
14+
class BaseFFN {
15+
FP wIn[INPUT_SIZE][HIDDEN1_SIZE], wHid1[HIDDEN1_SIZE][HIDDEN2_SIZE],
16+
wHid2[HIDDEN2_SIZE][OUTPUT_SIZE];
17+
FP bIn[INPUT_SIZE], bHid1[HIDDEN1_SIZE], b[OUTPUT_SIZE];
18+
void init_wb() {}
19+
20+
public:
21+
BaseFFN() { init_wb(); }
22+
FP (&forward())[OUTPUT_SIZE] {}
23+
};
24+
25+
} // namespace NN
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#pragma once
2+
3+
#include <memory>
4+
#include <vector>
5+
#include <chrono>
6+
#include <thread>
7+
#include <cmath>
8+
9+
namespace ELC{
10+
template<typename T>
11+
struct Node {
12+
size_t n;
13+
std::vector<std::shared_ptr<T>> data, muatan, impedansi;
14+
double timestep;
15+
16+
Node(size_t n, double timestep = 1e-7)
17+
: n(n), data(n), muatan(n), impedansi(n), timestep(timestep) {
18+
for (size_t i = 0; i < n; ++i) {
19+
data[i] = std::make_shared<T>(0);
20+
muatan[i] = std::make_shared<T>(0);
21+
impedansi[i] = std::make_shared<T>(1);
22+
}
23+
}
24+
25+
virtual ~Node() = default;
26+
27+
T& operator[](size_t i) { return this->data[i]; }
28+
const T& operator[](size_t i) const { return this->data[i]; }
29+
T& q(size_t i) { return *muatan[i]; }
30+
const T& q(size_t i) const { return *muatan[i]; }
31+
32+
virtual void updateTegangan() {
33+
for (size_t i = 0; i < n; ++i)
34+
this->data[i] = (*muatan[i]) * (*impedansi[i]);
35+
}
36+
37+
void connect(Node<T>& other, size_t pinThis, size_t pinOther) {
38+
if (pinThis >= n || pinOther >= other.n) return;
39+
data[pinThis] = other.data[pinOther];
40+
muatan[pinThis] = other.muatan[pinOther];
41+
impedansi[pinThis] = other.impedansi[pinOther];
42+
}
43+
44+
void setTimestep(double t) { timestep = t; }
45+
46+
void runLoop(size_t iterations = 100) {
47+
for (size_t i = 0; i < iterations; ++i) {
48+
auto start = std::chrono::high_resolution_clock::now();
49+
updateTegangan();
50+
auto end = std::chrono::high_resolution_clock::now();
51+
double dur = std::chrono::duration<double>(end - start).count();
52+
double sleepTime = timestep - dur;
53+
if (sleepTime > 0)
54+
std::this_thread::sleep_for(std::chrono::duration<double>(sleepTime));
55+
}
56+
}
57+
};
58+
59+
template<typename T>
60+
struct Kapasitor : Node<T> {
61+
T C; double dt; T I;
62+
Kapasitor(T C, double dt, double ts = 1e-7)
63+
: Node<T>(2, ts), C(C), dt(dt), I(0) {}
64+
65+
void alirkanArus(T Iin) {
66+
I = Iin;
67+
this->q(0) += I * dt;
68+
this->q(1) -= I * dt;
69+
}
70+
71+
void updateTegangan() override {
72+
T V = (this->q(0) - this->q(1)) / C;
73+
this->data[0] = V;
74+
this->data[1] = -V;
75+
}
76+
};
77+
78+
template<typename T>
79+
struct Induktor : Node<T> {
80+
T L; double dt; T I;
81+
Induktor(T L, double dt, double ts = 1e-7)
82+
: Node<T>(2, ts), L(L), dt(dt), I(0) {}
83+
84+
void terapkanTegangan(T V) {
85+
I += (V / L) * dt;
86+
}
87+
88+
void updateTegangan() override {
89+
this->data[0] = I;
90+
this->data[1] = -I;
91+
}
92+
};
93+
94+
template<typename T>
95+
struct Resistor : Node<T> {
96+
T R;
97+
Resistor(T R, double ts = 1e-7)
98+
: Node<T>(2, ts), R(R) {}
99+
100+
void updateTegangan() override {
101+
T V = this->q(0) * R;
102+
this->data[0] = V;
103+
this->data[1] = 0;
104+
}
105+
};
106+
107+
template<typename T>
108+
struct Transistor : Node<T> {
109+
T beta, Vth;
110+
Transistor(T beta, T Vth, double ts = 1e-7)
111+
: Node<T>(3, ts), beta(beta), Vth(Vth) {}
112+
113+
void updateTegangan() override {
114+
T Vbe = (this->data[1] - this->data[2]);
115+
T Ic = Vbe > Vth ? beta * (Vbe - Vth) : 0;
116+
this->q(0) = Ic; // kolektor muatan
117+
this->q(2) = -Ic; // emitor muatan
118+
this->data[0] = Ic;
119+
this->data[1] = Vbe;
120+
this->data[2] = 0;
121+
}
122+
};
123+
124+
template<typename T>
125+
struct Memristor : Node<T> {
126+
T M;
127+
Memristor(T M, double ts = 1e-7)
128+
: Node<T>(2, ts), M(M) {}
129+
130+
void updateTegangan() override {
131+
T V = M * this->q(0);
132+
this->data[0] = V;
133+
this->data[1] = -V;
134+
}
135+
};
136+
137+
template<typename T>
138+
struct Dioda : Node<T> {
139+
T I0, VT;
140+
Dioda(T I0, T VT, double ts = 1e-7)
141+
: Node<T>(2, ts), I0(I0), VT(VT) {}
142+
143+
void updateTegangan() override {
144+
T Iin = this->q(0);
145+
T V = Iin > 0 ? VT * std::log(Iin / I0) : 0;
146+
this->data[0] = V;
147+
this->data[1] = 0;
148+
}
149+
};
150+
151+
template<typename T>
152+
struct SumberTegangan : Node<T> {
153+
T Vsrc;
154+
SumberTegangan(T Vsrc, double ts = 1e-7)
155+
: Node<T>(2, ts), Vsrc(Vsrc) {}
156+
157+
void updateTegangan() override {
158+
this->data[0] = Vsrc;
159+
this->data[1] = 0;
160+
}
161+
};
162+
}

image/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_subdirectory(PNG)

image/PNG/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
include_directories(include)
2+
3+
#untuk kelas prime jadi include header dari subproject number_system
4+
include_directories(${CMAKE_SOURCE_DIR}/number_system/include)
5+
6+
set(SRC "src")
7+
8+
find_package(PNG REQUIRED)
9+
10+
add_executable(pngw ${SRC}/pngwriter.cxx)
11+
target_link_libraries(pngw PNG::PNG)

image/PNG/include/png.hxx

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#pragma once
2+
3+
#include <png.h>
4+
5+
#include <fstream>
6+
#include <stdexcept>
7+
#include <string>
8+
#include <vector>
9+
10+
class PNG {
11+
private:
12+
std::string fileName;
13+
std::ifstream input;
14+
std::ofstream output;
15+
png_structp pngPtr = nullptr;
16+
png_infop infoPtr = nullptr;
17+
int imageWidth = 0, imageHeight = 0;
18+
png_byte imageColorType = 0, imageBitDepth = 8;
19+
std::vector<png_byte> imageBuffer;
20+
21+
static void png_write_callback(png_structp png, png_bytep data,
22+
png_size_t length) {
23+
auto stream = reinterpret_cast<std::ostream *>(png_get_io_ptr(png));
24+
stream->write(reinterpret_cast<char *>(data), length);
25+
if (!*stream) png_error(png, "WRITE Error");
26+
}
27+
28+
static void png_read_callback(png_structp png, png_bytep data,
29+
png_size_t length) {
30+
auto stream = reinterpret_cast<std::istream *>(png_get_io_ptr(png));
31+
stream->read(reinterpret_cast<char *>(data), length);
32+
if (!*stream) png_error(png, "READ Error");
33+
}
34+
35+
int get_channel_count() const {
36+
switch (imageColorType) {
37+
case PNG_COLOR_TYPE_GRAY: return 1;
38+
case PNG_COLOR_TYPE_GRAY_ALPHA: return 2;
39+
case PNG_COLOR_TYPE_RGB: return 3;
40+
case PNG_COLOR_TYPE_RGBA: return 4;
41+
default: return 3;
42+
}
43+
}
44+
45+
public:
46+
PNG(const std::string &fileName) : fileName(fileName) {}
47+
48+
~PNG() {
49+
if (pngPtr) {
50+
if (input.is_open()) png_destroy_read_struct(&pngPtr, &infoPtr, nullptr);
51+
if (output.is_open()) png_destroy_write_struct(&pngPtr, &infoPtr);
52+
}
53+
}
54+
55+
bool read() {
56+
input.open(fileName, std::ios::binary);
57+
if (!input) return false;
58+
59+
pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr,
60+
nullptr);
61+
if (!pngPtr) return false;
62+
infoPtr = png_create_info_struct(pngPtr);
63+
if (!infoPtr || setjmp(png_jmpbuf(pngPtr))) return false;
64+
65+
png_set_read_fn(pngPtr, static_cast<void *>(&input), png_read_callback);
66+
png_read_info(pngPtr, infoPtr);
67+
68+
imageWidth = png_get_image_width(pngPtr, infoPtr);
69+
imageHeight = png_get_image_height(pngPtr, infoPtr);
70+
imageColorType = png_get_color_type(pngPtr, infoPtr);
71+
imageBitDepth = png_get_bit_depth(pngPtr, infoPtr);
72+
73+
png_read_update_info(pngPtr, infoPtr);
74+
75+
int rowBytes = png_get_rowbytes(pngPtr, infoPtr);
76+
imageBuffer.resize(imageHeight * rowBytes);
77+
std::vector<png_bytep> rows(imageHeight);
78+
for (int y = 0; y < imageHeight; y++) rows[y] = &imageBuffer[y * rowBytes];
79+
80+
png_read_image(pngPtr, rows.data());
81+
return true;
82+
}
83+
84+
bool write() {
85+
output.open(fileName, std::ios::binary);
86+
if (!output) return false;
87+
88+
int rowBytes = imageWidth * get_channel_count();
89+
if (imageBuffer.size() != static_cast<size_t>(imageHeight * rowBytes))
90+
imageBuffer.resize(imageHeight * rowBytes);
91+
92+
pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr,
93+
nullptr);
94+
if (!pngPtr) return false;
95+
infoPtr = png_create_info_struct(pngPtr);
96+
if (!infoPtr || setjmp(png_jmpbuf(pngPtr))) return false;
97+
98+
png_set_write_fn(pngPtr, static_cast<void *>(&output), png_write_callback,
99+
nullptr);
100+
png_set_IHDR(pngPtr, infoPtr, imageWidth, imageHeight, imageBitDepth,
101+
imageColorType, PNG_INTERLACE_NONE,
102+
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
103+
png_write_info(pngPtr, infoPtr);
104+
105+
std::vector<png_bytep> rows(imageHeight);
106+
for (int y = 0; y < imageHeight; y++) rows[y] = &imageBuffer[y * rowBytes];
107+
108+
png_write_image(pngPtr, rows.data());
109+
png_write_end(pngPtr, nullptr);
110+
return true;
111+
}
112+
113+
png_byte &pixel(int x, int y, int channel = 0) {
114+
return imageBuffer[(y * imageWidth + x) * get_channel_count() + channel];
115+
}
116+
117+
// Getters
118+
int get_width() const { return imageWidth; }
119+
int get_height() const { return imageHeight; }
120+
png_byte get_color_type() const { return imageColorType; }
121+
png_byte get_bit_depth() const { return imageBitDepth; }
122+
const std::vector<png_byte> &get_buffer() const { return imageBuffer; }
123+
124+
// Setters
125+
void set_width(int w) { imageWidth = w; }
126+
void set_height(int h) { imageHeight = h; }
127+
void set_color_type(png_byte ct) { imageColorType = ct; }
128+
void set_bit_depth(png_byte bd) { imageBitDepth = bd; }
129+
void set_buffer(const std::vector<png_byte> &buf) { imageBuffer = buf; }
130+
};

0 commit comments

Comments
 (0)