diff --git a/.gitignore b/.gitignore index c8f8dca..8920a38 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ wheels/ .venv # -.vscode \ No newline at end of file +.vscode +out \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..323f755 --- /dev/null +++ b/Makefile @@ -0,0 +1,61 @@ +BUILD_DIR := ./build +CC := gcc +CFLAGS := -Wall -g -std=c90 +LDFLAGS := -lm + +LIB_DIR := ./lib/nr/ansi +LIB_INCLUDE := $(LIB_DIR)/other +LIB_SRCS := $(LIB_DIR)/recipes/machar.c +LIB_OBJS := $(patsubst %.c,$(BUILD_DIR)/lib/%.o,$(notdir $(LIB_SRCS))) + +HW_DIR := ./hws + +ifeq ($(strip $(hw)),) + +else + TARGET_NAME := hw$(hw) + SRC_DIR := $(HW_DIR)/hw$(hw) +endif + +ifeq ($(strip $(TARGET_NAME)),) +all: + @echo "에러: 'target'을 지정해주세요." +else + TARGET_EXEC := $(BUILD_DIR)/$(TARGET_NAME).out + TARGET_SRCS := $(wildcard $(SRC_DIR)/*.c) + TARGET_OBJS := $(patsubst %.c,$(BUILD_DIR)/hw$(hw)/%.o,$(notdir $(TARGET_SRCS))) + OBJS := $(TARGET_OBJS) $(LIB_OBJS) + SRCS := $(TARGET_SRCS) $(LIB_SRCS) +all: run +endif + +init: + @mkdir -p $(BUILD_DIR) + @mkdir -p $(BUILD_DIR)/lib + @mkdir -p $(BUILD_DIR)/$(TARGET_NAME) + +clean: + @echo "빌드 결과물을 삭제합니다..." + @rm -rf $(BUILD_DIR) + +build: init $(TARGET_EXEC) + @echo "빌드 완료" + +$(TARGET_EXEC): $(OBJS) + @echo "링킹 중: $@" + $(CC) $(CFLAGS) $(LDFLAGS) $^ -o $@ + +$(OBJS): %.o: + @echo "컴파일 중: $@" + $(eval TARGET_C_BASENAME := $(patsubst %.o,%.c,$(notdir $@))) + $(eval FOUND_SRC := $(foreach src,$(SRCS),$(if $(filter $(TARGET_C_BASENAME),$(notdir $(src))),$(src)))) + $(CC) $(CFLAGS) $(LDFLAGS) -I $(LIB_INCLUDE) -c $(FOUND_SRC) -o $@ + +run: clean build + @echo "실행 시작" + @echo "============" + @$(TARGET_EXEC) + +dist: + mkdir -p out + zip -j -9 out/$(TARGET_NAME).zip $(TARGET_SRCS) \ No newline at end of file diff --git a/hws/hw1/Makefile b/hws/hw1/Makefile deleted file mode 100644 index e69de29..0000000 diff --git a/hws/hw1/main.c b/hws/hw1/main.c index e69de29..071831f 100644 --- a/hws/hw1/main.c +++ b/hws/hw1/main.c @@ -0,0 +1,175 @@ +#include "nr.h" +#include +#include + +void get_eps(float *eps) { + *eps = 1.0f; + + while ((1.0f + *eps / 2.0f) > 1.0f) { + *eps /= 2.0f; + } +} + +void get_eps_double(double *eps) { + *eps = 1.0; + + while ((1.0 + *eps / 2.0) > 1.0) { + *eps /= 2.0; + } +} + +#define CONV(i) ((double) (i)) + +void machar_double(int *ibeta, int *it, int *irnd, int *ngrd, int *machep, int *negep, int *iexp, int *minexp, int *maxexp, + double *eps, double *epsneg, double *xmin, double *xmax) { + int i, itemp, iz, j, k, mx, nxres; + double a, b, beta, betah, betain, one, t, temp, temp1, tempa, two, y, z, zero; + + one = CONV(1); + two = one + one; + zero = one - one; + a = one; + do { + a += a; + temp = a + one; + temp1 = temp - a; + } while (temp1 - one == zero); + b = one; + do { + b += b; + temp = a + b; + itemp = (int) (temp - a); + } while (itemp == 0); + *ibeta = itemp; + beta = CONV(*ibeta); + *it = 0; + b = one; + do { + ++(*it); + b *= beta; + temp = b + one; + temp1 = temp - b; + } while (temp1 - one == zero); + *irnd = 0; + betah = beta / two; + temp = a + betah; + if (temp - a != zero) *irnd = 1; + tempa = a + beta; + temp = tempa + betah; + if (*irnd == 0 && temp - tempa != zero) *irnd = 2; + *negep = (*it) + 3; + betain = one / beta; + a = one; + for (i = 1; i <= (*negep); i++) a *= betain; + b = a; + for (;;) { + temp = one - a; + if (temp - one != zero) break; + a *= beta; + --(*negep); + } + *negep = -(*negep); + *epsneg = a; + *machep = -(*it) - 3; + a = b; + for (;;) { + temp = one + a; + if (temp - one != zero) break; + a *= beta; + ++(*machep); + } + *eps = a; + *ngrd = 0; + temp = one + (*eps); + if (*irnd == 0 && temp * one - one != zero) *ngrd = 1; + i = 0; + k = 1; + z = betain; + t = one + (*eps); + nxres = 0; + for (;;) { + y = z; + z = y * y; + a = z * one; + temp = z * t; + if (a + a == zero || fabs(z) >= y) break; + temp1 = temp * betain; + if (temp1 * beta == z) break; + ++i; + k += k; + } + if (*ibeta != 10) { + *iexp = i + 1; + mx = k + k; + } else { + *iexp = 2; + iz = (*ibeta); + while (k >= iz) { + iz *= *ibeta; + ++(*iexp); + } + mx = iz + iz - 1; + } + for (;;) { + *xmin = y; + y *= betain; + a = y * one; + temp = y * t; + if (a + a != zero && fabs(y) < *xmin) { + ++k; + temp1 = temp * betain; + if (temp1 * beta == y && temp != y) { + nxres = 3; + *xmin = y; + break; + } + } else + break; + } + *minexp = -k; + if (mx <= k + k - 3 && *ibeta != 10) { + mx += mx; + ++(*iexp); + } + *maxexp = mx + (*minexp); + *irnd += nxres; + if (*irnd >= 2) *maxexp -= 2; + i = (*maxexp) + (*minexp); + if (*ibeta == 2 && !i) --(*maxexp); + if (i > 20) --(*maxexp); + if (a != y) *maxexp -= 2; + *xmax = one - (*epsneg); + if ((*xmax) * one != *xmax) *xmax = one - beta * (*epsneg); + *xmax /= (*xmin * beta * beta * beta); + i = (*maxexp) + (*minexp) + 3; + for (j = 1; j <= i; j++) { + if (*ibeta == 2) *xmax += *xmax; + else + *xmax *= beta; + } +} +#undef CONV + +int main() { + int ibeta, it, irnd, ngrd, machep, negep, iexp, minexp, maxexp; + float eps, epsneg, xmin, xmax; + + machar(&ibeta, &it, &irnd, &ngrd, &machep, &negep, &iexp, &minexp, &maxexp, + &eps, &epsneg, &xmin, &xmax); + + printf("Machine Accuracy for float (machar): \t\t%0.20f\n", eps); + + get_eps(&eps); + + printf("Machine Accuracy for float (get_eps): \t\t%0.20f\n", eps); + double eps_double, epsneg_double, xmin_double, xmax_double; + + machar_double(&ibeta, &it, &irnd, &ngrd, &machep, &negep, &iexp, &minexp, &maxexp, + &eps_double, &epsneg_double, &xmin_double, &xmax_double); + printf("Machine Accuracy for double (machar_double): \t%0.20f\n", eps_double); + + get_eps_double(&eps_double); + printf("Machine Accuracy for double (get_eps_double): \t%0.20f\n", eps_double); + + return 0; +}