diff --git a/Makefile b/Makefile index 8d30722..71cb95a 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,11 @@ run: @for dir in $(SUBDIRS); do \ echo "=== Running $$dir ==="; \ (cd $$dir && $(MAKE) SANITIZE=$(SANITIZE) run) || exit 1; \ + ## Run tests if present and fail the test if tests fail \ + if [ -f "$$dir/tests.sh" ]; then \ + echo "=== Running tests in $$dir ==="; \ + (cd $$dir && ./tests.sh) || exit 1; \ + fi; \ done # -------------------------- diff --git a/README.md b/README.md index 2862aa9..061480d 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ Examples include (and will expand to): * Parallelism * [parallel-transform](./parallel-transform/) * Performance‑oriented C++ idioms +* Algorithms + * [integer-factorization](./integer-factorization/) --- @@ -171,7 +173,7 @@ The CI setup requires **no updates** when new example folders are added. The CI will perform: 1. `./clang-check.sh *.cpp *.hpp` 2. `make SANITIZE=[address, thread, undefined]` -3. `make run` +3. `make run` which will run `make run` for each project and `./tests.sh` if it is present. --- diff --git a/fold-left-fold-right/Makefile b/fold-left-fold-right/Makefile index 7b9a123..6e5fc0f 100644 --- a/fold-left-fold-right/Makefile +++ b/fold-left-fold-right/Makefile @@ -5,7 +5,7 @@ include ../common.mk # CXXFLAGS += -pthread TARGET := $(notdir $(CURDIR)) -SRCS := main.cpp +SRCS := $(wildcard *.cpp) OBJS := $(SRCS:.cpp=.o) all: $(TARGET) diff --git a/integer-factorization/Makefile b/integer-factorization/Makefile new file mode 100644 index 0000000..ab8b3c0 --- /dev/null +++ b/integer-factorization/Makefile @@ -0,0 +1,31 @@ +# pull in shared compiler settings +include ../common.mk + +# per-example flags +# CXXFLAGS += -pthread + +## get it from the folder name +TARGET := $(notdir $(CURDIR)) +## all *.cpp files in this folder +SRCS := $(wildcard *.cpp) +OBJS := $(SRCS:.cpp=.o) + +all: $(TARGET) + +$(TARGET): $(OBJS) + $(CXX) $(CXXFLAGS) -o $@ $^ + +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ + +run: $(TARGET) + ./$(TARGET) $(ARGS) + +clean: + rm -f $(OBJS) $(TARGET) + +# Delegates to top-level Makefile +check-format: + $(MAKE) -f ../Makefile check-format DIR=$(CURDIR) + +.PHONY: all clean run check-format diff --git a/integer-factorization/factorization_algorithms.cpp b/integer-factorization/factorization_algorithms.cpp new file mode 100644 index 0000000..5ab3335 --- /dev/null +++ b/integer-factorization/factorization_algorithms.cpp @@ -0,0 +1,17 @@ +#include "factorization_algorithms.hpp" + +std::vector +trial_division(long long n) +{ + std::vector factors; + for (long long i = 2; i * i <= n; ++i) { + while (n % i == 0) { + factors.push_back(i); + n /= i; + } + } + if (n > 1) { + factors.push_back(n); + } + return factors; +} diff --git a/integer-factorization/factorization_algorithms.hpp b/integer-factorization/factorization_algorithms.hpp new file mode 100644 index 0000000..c6202f2 --- /dev/null +++ b/integer-factorization/factorization_algorithms.hpp @@ -0,0 +1,13 @@ +/** + * This header file declares the function prototypes for various integer factorization algorithms. + */ + +#ifndef FACTORIZATION_ALGORITHMS_H +#define FACTORIZATION_ALGORITHMS_H + +#include + +std::vector +trial_division(long long n); + +#endif // FACTORIZATION_ALGORITHMS_H \ No newline at end of file diff --git a/integer-factorization/main.cpp b/integer-factorization/main.cpp new file mode 100644 index 0000000..1dae480 --- /dev/null +++ b/integer-factorization/main.cpp @@ -0,0 +1,98 @@ +/** + * This program implements various algorithms for integer factorization, + * It takes integer(s) from the command line or a file and outputs their prime + * factorizations. + * + * Usage: + * ./integer-factorization [options] [integers...] + * Options: + * -h, --help Show this help message and exit + * -f, --file FILE Read integers from FILE, one per line + * -o, --output FILE Write output to FILE instead of stdout + */ + +#include +#include +#include +#include +#include +#include "factorization_algorithms.hpp" + +void +print_help() +{ + std::cout << "Usage: ./integer-factorization [options] [integers...]\n" + << "Options:\n" + << " -h, --help Show this help message and exit\n" + << " -f, --file FILE Read integers from FILE, one per line\n" + << " -o, --output FILE Write output to FILE instead of stdout\n"; +} + +int +main(int argc, char* argv[]) +{ + std::string input_file; + std::string output_file; + std::vector numbers; + + static struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"file", required_argument, 0, 'f'}, + {"output", required_argument, 0, 'o'}, + {0, 0, 0, 0}}; + + int opt; + while ((opt = getopt_long(argc, argv, "hf:o:", long_options, NULL)) != -1) { + switch (opt) { + case 'h': + print_help(); + return 0; + case 'f': + input_file = optarg; + break; + case 'o': + output_file = optarg; + break; + default: + print_help(); + return 1; + } + } + + // Read numbers from file if specified + if (!input_file.empty()) { + std::ifstream infile(input_file); + long long num; + while (infile >> num) { + numbers.push_back(num); + } + } + + // Read numbers from command line arguments + for (int index = optind; index < argc; index++) { + numbers.push_back(std::stoll(argv[index])); + } + + // Prepare output stream + std::ostream* out_stream = &std::cout; + std::ofstream outfile; + if (!output_file.empty()) { + outfile.open(output_file); + out_stream = &outfile; + } + + // Factor each number and output the result + for (const auto& number : numbers) { + std::vector factors; + factors = trial_division(number); + *out_stream << "Factors of " << number << ": "; + for (const auto& factor : factors) { + *out_stream << factor << " "; + } + *out_stream << "\n"; + } + if (outfile.is_open()) { + outfile.close(); + } + return 0; +} diff --git a/integer-factorization/tests.sh b/integer-factorization/tests.sh new file mode 100755 index 0000000..4dedbce --- /dev/null +++ b/integer-factorization/tests.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -ex + +./integer-factorization -h + +./integer-factorization 1234 45678 diff --git a/parallel-transform/Makefile b/parallel-transform/Makefile index 8024040..172da2f 100644 --- a/parallel-transform/Makefile +++ b/parallel-transform/Makefile @@ -6,7 +6,7 @@ include ../common.mk ## get it from the folder name TARGET := $(notdir $(CURDIR)) -SRCS := main.cpp +SRCS := $(wildcard *.cpp) OBJS := $(SRCS:.cpp=.o) all: $(TARGET) diff --git a/smart-ptr/Makefile b/smart-ptr/Makefile index 60d49d6..172da2f 100644 --- a/smart-ptr/Makefile +++ b/smart-ptr/Makefile @@ -4,18 +4,27 @@ include ../common.mk # per-example flags # CXXFLAGS += -pthread +## get it from the folder name TARGET := $(notdir $(CURDIR)) -SRCS = main.cpp +SRCS := $(wildcard *.cpp) +OBJS := $(SRCS:.cpp=.o) all: $(TARGET) -$(TARGET): $(SRCS) - $(CXX) $(CXXFLAGS) -o $(TARGET) $(SRCS) +$(TARGET): $(OBJS) + $(CXX) $(CXXFLAGS) -o $@ $^ + +%.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ run: $(TARGET) ./$(TARGET) $(ARGS) clean: - rm -f $(TARGET) + rm -f $(OBJS) $(TARGET) + +# Delegates to top-level Makefile +check-format: + $(MAKE) -f ../Makefile check-format DIR=$(CURDIR) -.PHONY: all clean +.PHONY: all clean run check-format diff --git a/thread-safe-queue/Makefile b/thread-safe-queue/Makefile index 941ebb4..01919ed 100644 --- a/thread-safe-queue/Makefile +++ b/thread-safe-queue/Makefile @@ -5,7 +5,7 @@ include ../common.mk CXXFLAGS += -pthread TARGET := $(notdir $(CURDIR)) -SRCS := main.cpp +SRCS := $(wildcard *.cpp) OBJS := $(SRCS:.cpp=.o) all: $(TARGET) diff --git a/unique-ptr-basics/Makefile b/unique-ptr-basics/Makefile index 2c48d2b..e41b505 100644 --- a/unique-ptr-basics/Makefile +++ b/unique-ptr-basics/Makefile @@ -5,7 +5,7 @@ include ../common.mk # CXXFLAGS += -pthread TARGET := $(notdir $(CURDIR)) -SRCS := main.cpp +SRCS := $(wildcard *.cpp) OBJS := $(SRCS:.cpp=.o) all: $(TARGET) diff --git a/views-zip-enumerate/Makefile b/views-zip-enumerate/Makefile index 7b9a123..6e5fc0f 100644 --- a/views-zip-enumerate/Makefile +++ b/views-zip-enumerate/Makefile @@ -5,7 +5,7 @@ include ../common.mk # CXXFLAGS += -pthread TARGET := $(notdir $(CURDIR)) -SRCS := main.cpp +SRCS := $(wildcard *.cpp) OBJS := $(SRCS:.cpp=.o) all: $(TARGET)