Skip to content

Commit d3318e0

Browse files
committed
Initial commit.
0 parents  commit d3318e0

File tree

6 files changed

+269
-0
lines changed

6 files changed

+269
-0
lines changed

.clang-format

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
BasedOnStyle: LLVM
2+
IndentWidth: 4
3+
ColumnLimit: 120
4+
AllowShortIfStatementsOnASingleLine: true

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Developer artifacts
2+
.cache/
3+
compile_commands.json
4+
5+
# Compilation
6+
*.o
7+
quadratic

LICENSE.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Matteo Golin
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Makefile

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
CC = gcc
2+
OUT = quadratic
3+
4+
# Compilation warnings
5+
WARNINGS += -Wall -Wextra -Wshadow -Wundef -Wformat=2 -Wtrampolines -Wfloat-equal
6+
WARNINGS += -Wbad-function-cast -Wstrict-prototypes -Wpacked
7+
WARNINGS += -Wno-aggressive-loop-optimizations -Wmissing-prototypes -Winit-self
8+
WARNINGS += -Wmissing-declarations -Wmissing-format-attribute -Wunreachable-code
9+
WARNINGS += -Wshift-overflow=2 -Wduplicated-cond -Wpointer-arith -Wwrite-strings
10+
WARNINGS += -Wnested-externs -Wcast-align -Wredundant-decls
11+
WARNINGS += -Werror=implicit-function-declaration -Wlogical-not-parentheses
12+
WARNINGS += -Wlogical-op -Wold-style-definition -Wcast-qual -Wdouble-promotion
13+
WARNINGS += -Wunsuffixed-float-constants -Wmissing-include-dirs -Wnormalized
14+
WARNINGS += -Wdisabled-optimization -Wsuggest-attribute=const
15+
16+
# Compilation flags
17+
CFLAGS = -O3 -lm
18+
19+
# Source files
20+
SRCDIR = .
21+
SRCS = $(wildcard $(SRCDIR)/*.c)
22+
OBJS = $(patsubst %.c,%.o,$(SRCS))
23+
24+
%.o: %.c
25+
$(CC) $(CFLAGS) $(WARNINGS) -o $@ -c $<
26+
27+
all: $(OBJS)
28+
$(CC) $(CFLAGS) $^ -o $(OUT)
29+
30+
clean:
31+
@rm $(OBJS)

README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# quadratic
2+
3+
A simple command line program for solving the quadratic equation. I built this purely to save me a little time when
4+
doing algebra for my engineering homework. The quadratic formula shows up quite often in circuit problems for non-linear
5+
circuits, and it becomes tedious to evaluate the quadratic formula each time.
6+
7+
# Usage
8+
9+
To see usage instructions for this program, please run `quadratic -h`.
10+
11+
Example output:
12+
13+
```console
14+
[user]$ quadratic -- 1 -10 16
15+
1.000000x^2 + -10.000000x + 16.000000
16+
x = 8.000000
17+
x = 2.000000
18+
19+
[user]$ quadratic -v y -- 1 -10 16
20+
1.000000y^2 + 2.000000y + 3.000000
21+
x = -1.000000 + 1.414214i
22+
x = -1.000000 + -1.414214i
23+
24+
```
25+
26+
# Build/Installation
27+
28+
The build recipe is in the Makefile. Running `make all` will create a binary called `quadratic` which you can then run.
29+
30+
Although only tested on Linux, this program should build and run just fine on all other platforms.

main.c

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
#include <getopt.h>
2+
#include <math.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
6+
/** Program version. */
7+
#define VERSION "0.0.0"
8+
9+
/** Struct to represent a quadratic polynomial of format ax^2 + bx + c. */
10+
struct quadratic_t {
11+
double a; /**< The a coefficient. */
12+
double b; /**< The b coefficient. */
13+
double c; /**< The c coefficient. */
14+
};
15+
16+
/** Struct to represent a complex number. */
17+
struct complex_t {
18+
double re; /**< The real component. */
19+
double im; /**< The imaginary component. */
20+
};
21+
22+
/** By default show the equation using the variable x. */
23+
static char variable = 'x';
24+
25+
/** Check that the coefficient exists. */
26+
#define check_coeff(coeff) \
27+
if (optind >= argc) { \
28+
fprintf(stderr, "Missing coefficient '" coeff "'\n"); \
29+
print_usage(); \
30+
exit(EXIT_FAILURE); \
31+
}
32+
33+
void print_usage(void);
34+
void print_complex(struct complex_t *c);
35+
void quadratic_formula(struct quadratic_t *poly, struct complex_t *z0, struct complex_t *z1);
36+
37+
int main(int argc, char **argv) {
38+
39+
/* Parse options. */
40+
int c;
41+
while ((c = getopt(argc, argv, ":hv:")) != -1) {
42+
switch (c) {
43+
case 'h':
44+
print_usage();
45+
exit(EXIT_SUCCESS);
46+
case 'v':
47+
variable = optarg[0];
48+
break;
49+
case ':':
50+
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
51+
print_usage();
52+
exit(EXIT_FAILURE);
53+
case '?':
54+
fprintf(stderr, "Unknown option `-%c'.\n", optopt);
55+
print_usage();
56+
exit(EXIT_FAILURE);
57+
default:
58+
print_usage();
59+
exit(EXIT_FAILURE);
60+
}
61+
}
62+
63+
/* Parse all three coefficients. */
64+
struct quadratic_t polynomial;
65+
66+
check_coeff("a");
67+
polynomial.a = strtod(argv[optind], NULL);
68+
optind++;
69+
70+
check_coeff("b");
71+
polynomial.b = strtod(argv[optind], NULL);
72+
optind++;
73+
74+
check_coeff("c");
75+
polynomial.c = strtod(argv[optind], NULL);
76+
optind++;
77+
78+
/** Plug coefficients into the quadratic formula and determine the zero. */
79+
struct complex_t z0;
80+
struct complex_t z1;
81+
quadratic_formula(&polynomial, &z0, &z1);
82+
83+
/** Display results. */
84+
printf("%lf%c^2 + %lf%c + %lf\n", polynomial.a, variable, polynomial.b, variable, polynomial.c);
85+
86+
// First zero
87+
printf("x = ");
88+
print_complex(&z0);
89+
putchar('\n');
90+
91+
// Second zero
92+
printf("x = ");
93+
print_complex(&z1);
94+
putchar('\n');
95+
96+
return EXIT_SUCCESS;
97+
}
98+
99+
/**
100+
* Performs the quadratic formula calculation to find two zeros for a polynomial.
101+
* @param poly The polynomial to use for the calculation.
102+
* @param z0 Where the first calculated zero of the polynomial will be stored.
103+
* @param z1 Where the second calculated zero of the polynomial will be stored.
104+
*/
105+
void quadratic_formula(struct quadratic_t *poly, struct complex_t *z0, struct complex_t *z1) {
106+
107+
double discriminant = (poly->b * poly->b) - 4.0 * poly->a * poly->c;
108+
double denominator = (2.0 * poly->a); // 2a term in denominator
109+
110+
// Non complex roots
111+
if (discriminant >= 0.0) {
112+
z0->re = (-poly->b + sqrt(discriminant)) / denominator;
113+
z1->re = (-poly->b - sqrt(discriminant)) / denominator;
114+
z0->im = 0.0;
115+
z1->im = 0.0;
116+
return;
117+
}
118+
119+
// Both zeroes will have the same real component
120+
z0->re = -poly->b / denominator;
121+
z1->re = z0->re;
122+
123+
// Zeroes will have complementary imaginary components
124+
z0->im = sqrt(-discriminant) / denominator;
125+
z1->im = -z0->im;
126+
}
127+
128+
/**
129+
* Prints a complex number to stdout.
130+
* @param c The complex number to print.
131+
*/
132+
void print_complex(struct complex_t *c) {
133+
134+
// Don't print the imaginary component if there is none
135+
if (c->im == 0.0) {
136+
printf("%lf", c->re);
137+
return;
138+
}
139+
140+
printf("%lf + %lfi", c->re, c->im);
141+
}
142+
143+
/**
144+
* Prints usage information about the command line program.
145+
*/
146+
void print_usage(void) {
147+
puts("quadratic v" VERSION);
148+
puts("MIT License | By Matteo Golin, 2024");
149+
putchar('\n');
150+
puts("DESCRIPTION:");
151+
puts("\tFinds the zeroes of a quadratic polynomial in form ax^2 + bx + c.");
152+
putchar('\n');
153+
puts("USAGE:");
154+
puts("\tquadratic [options] -- a b c");
155+
puts("\tEnsure you include the '--' before the coefficients so negative numbers are properly parsed.");
156+
putchar('\n');
157+
puts("EXAMPLES:");
158+
puts("\tquadratic -- 1 -10 16");
159+
puts("\t1.000000x^2 + -10.000000x + 16.000000");
160+
puts("\tx = 8.000000");
161+
puts("\tx = 2.000000");
162+
putchar('\n');
163+
puts("\tquadratic -v y -- 1 -10 16");
164+
puts("\t1.000000y^2 + 2.000000y + 3.000000");
165+
puts("\tx = -1.000000 + 1.414214i");
166+
puts("\tx = -1.000000 + -1.414214i");
167+
putchar('\n');
168+
puts("ARGUMENTS");
169+
puts("\ta\tThe value of the a coefficient of the polynomial.");
170+
puts("\tb\tThe value of the b coefficient of the polynomial.");
171+
puts("\tc\tThe value of the c coefficient of the polynomial.");
172+
putchar('\n');
173+
puts("OPTIONS:");
174+
puts("\tv\tThe variable to show as being solved for in the quadratic equation. Defaults to x.");
175+
puts("\th\tPrints this help screen and exits.");
176+
}

0 commit comments

Comments
 (0)