aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Elliott Hand <jhand@hawaii.edu>2026-05-01 17:42:34 -1000
committerJoseph Elliott Hand <jhand@hawaii.edu>2026-05-01 17:52:21 -1000
commita344af24f685dc124489b76e38d56b76ab7bf235 (patch)
tree8c579571b6d9ea262816b6d387c61b469dcb2084
parent56529d472f61dba8d01af27a792b5d14df1b2c2e (diff)
downloadunit.h-a344af24f685dc124489b76e38d56b76ab7bf235.tar.gz
Refactoring and code style improvementsHEADmaster
Signed-off-by: Joseph Elliott Hand <jhand@hawaii.edu>
-rw-r--r--.clang-format1
-rw-r--r--unit.h208
2 files changed, 98 insertions, 111 deletions
diff --git a/.clang-format b/.clang-format
index 55bb745..61a3de0 100644
--- a/.clang-format
+++ b/.clang-format
@@ -8,6 +8,7 @@ AlignConsecutiveAssignments:
Enabled: true
AlignConsecutiveDeclarations:
Enabled: true
+AlignArrayOfStructures: Left
AlwaysBreakAfterDefinitionReturnType: All
diff --git a/unit.h b/unit.h
index 32a26c0..997852d 100644
--- a/unit.h
+++ b/unit.h
@@ -1,29 +1,29 @@
/*
* unit.h - Small library for handling dimensioned quantities in C.
* Copyright (C) 2026 Joseph Hand
- *
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-
+
#ifndef _UNITH
#define _UNITH
-#define U(str) get_unit_value(str)
+#define U(str) unith_parse_compound_unit(str)
#define UFMT "%.3e %s"
-#define UARG(value, units) ((value) / get_unit_value(units)), (units)
+#define UARG(value, units) ((value) / unith_parse_compound_unit(units)), (units)
-double get_unit_value(char const * string);
+double unith_parse_compound_unit(char const * string);
#ifdef UNITH_IMPL
@@ -33,76 +33,12 @@ double get_unit_value(char const * string);
#include <stdlib.h>
#include <string.h>
+#define LEN(a) ((int)(sizeof(a) / sizeof((a)[0])))
+
typedef struct {
char abbr[8];
double value;
-} Unit;
-
-double unit_prefixes[255] = {
- ['Q'] = 1e30,
- ['R'] = 1e27,
- ['Y'] = 1e24,
- ['Z'] = 1e21,
- ['E'] = 1e18,
- ['P'] = 1e15,
- ['T'] = 1e12,
- ['G'] = 1e9,
- ['M'] = 1e6,
- ['k'] = 1e3,
- ['h'] = 1e2,
- ['d'] = 1e-1,
- ['c'] = 1e-2,
- ['m'] = 1e-3,
- ['u'] = 1e-6,
- ['n'] = 1e-9,
- ['p'] = 1e-12,
- ['f'] = 1e-15,
- ['a'] = 1e-18,
- ['z'] = 1e-21,
- ['y'] = 1e-24,
- ['r'] = 1e-27,
- ['q'] = 1e-30
-};
-
-Unit units[] = {
-
- {"rad", 1},
- {"deg", 0.01745329252},
- {"arcmin", 0.0002908882087},
- {"arcsec", 0.000004848136811},
-
- {"sr", 1.0},
-
- {"s", 1.0},
- {"m", 1.0},
- {"g", 0.001},
- {"A", 1.0},
- {"K", 1.0},
- {"Hz", 1.0},
- {"N", 1.0},
- {"Pa", 1.0},
- {"J", 1.0},
- {"W", 1.0},
- {"C", 1.0},
- {"V", 1.0},
- {"Wb", 1.0},
- {"T", 1.0},
- {"F", 1.0},
- {"Ohm", 1.0},
- {"S", 1.0},
- {"H", 1.0},
-
- {"Jy", 1e-27},
- {"AU", 1.495978707e11},
- {"pc", 3.0857e16},
-
- {"Msun", 1.99e30},
- {"Mearth", 5.9722e24},
- {"Mjup", 1.89813e27},
-
- {"Rsun", 6.957e8},
- {"Rearth", 6.371e6},
- {"Rjup", 7.1492e7}};
+} unith_Unit;
typedef struct {
enum { SPACE, ONE, SLASH, EXP, NAME, NUMBER } type;
@@ -110,10 +46,61 @@ typedef struct {
char str[8];
double num;
} value;
-} Token;
+} unith_Token;
+
+int unith_get_token(char const * str, unith_Token * token);
+double unith_parse_unit(char const * name);
+double unith_parse_compound_unit(char const * string);
+
+double unith_prefixes[255] = {
+ ['Q'] = 1e30, ['R'] = 1e27, ['Y'] = 1e24, ['Z'] = 1e21, ['E'] = 1e18,
+ ['P'] = 1e15, ['T'] = 1e12, ['G'] = 1e9, ['M'] = 1e6, ['k'] = 1e3,
+ ['h'] = 1e2, ['d'] = 1e-1, ['c'] = 1e-2, ['m'] = 1e-3, ['u'] = 1e-6,
+ ['n'] = 1e-9, ['p'] = 1e-12, ['f'] = 1e-15, ['a'] = 1e-18, ['z'] = 1e-21,
+ ['y'] = 1e-24, ['r'] = 1e-27, ['q'] = 1e-30};
+
+unith_Unit unith_units[] = {
+ {"rad", 1 },
+ {"deg", 0.01745329252 },
+ {"arcmin", 0.0002908882087 },
+ {"arcsec", 0.000004848136811},
+
+ {"sr", 1.0 },
+
+ {"s", 1.0 },
+ {"m", 1.0 },
+ {"g", 0.001 },
+ {"A", 1.0 },
+ {"K", 1.0 },
+ {"Hz", 1.0 },
+ {"N", 1.0 },
+ {"Pa", 1.0 },
+ {"J", 1.0 },
+ {"W", 1.0 },
+ {"C", 1.0 },
+ {"V", 1.0 },
+ {"Wb", 1.0 },
+ {"T", 1.0 },
+ {"F", 1.0 },
+ {"Ohm", 1.0 },
+ {"S", 1.0 },
+ {"H", 1.0 },
+
+ {"Jy", 1e-27 },
+ {"AU", 1.495978707e11 },
+ {"pc", 3.0857e16 },
+
+ {"Msun", 1.99e30 },
+ {"Mearth", 5.9722e24 },
+ {"Mjup", 1.89813e27 },
+
+ {"Rsun", 6.957e8 },
+ {"Rearth", 6.371e6 },
+ {"Rjup", 7.1492e7 }
+};
int
-get_token(char const * str, Token * token) {
+unith_get_token(char const * str, unith_Token * token) {
int len = 0;
@@ -127,7 +114,7 @@ get_token(char const * str, Token * token) {
return len;
}
- if (str[0] == 1 && (str[1] < '0' || str[1] > '9') && str[1] != '.') {
+ if (str[0] == '1' && (str[1] < '0' || str[1] > '9') && str[1] != '.') {
token->type = ONE;
return 1;
}
@@ -169,34 +156,35 @@ get_token(char const * str, Token * token) {
}
double
-resolve_unit_name(char const * name) {
-
- double prefix_amount = unit_prefixes[name[0]];
- if(prefix_amount > 0) {
- for (int j = 0; j < sizeof(units) / sizeof(units[0]); j++) {
- if (strcmp(&name[1], units[j].abbr)) continue;
- return prefix_amount * units[j].value;
+unith_parse_unit(char const * name) {
+
+ double prefix_amount = unith_prefixes[(unsigned int)name[0]];
+ if (prefix_amount > 0) {
+ for (int j = 0; j < LEN(unith_units); j++) {
+ if (strcmp(&name[1], unith_units[j].abbr)) continue;
+ return prefix_amount * unith_units[j].value;
}
}
- for (int j = 0; j < sizeof(units) / sizeof(units[0]); j++) {
- if (strcmp(name, units[j].abbr)) continue;
- return units[j].value;
+ for (int j = 0; j < LEN(unith_units); j++) {
+ if (strcmp(name, unith_units[j].abbr)) continue;
+ return unith_units[j].value;
}
-
+
return 0.0;
}
double
-get_unit_value(char const * string) {
+unith_parse_compound_unit(char const * string) {
- int offset = 0;
- int token_count = 0;
- Token tokens[32];
+ int offset = 0;
+ int token_count = 0;
+ unith_Token tokens[32];
for (;;) {
- int result = get_token(string + offset, &tokens[token_count]);
+ int result =
+ unith_get_token(string + offset, &tokens[token_count]);
if (result < 0) {
goto error;
@@ -215,37 +203,35 @@ get_unit_value(char const * string) {
for (; i < token_count;) {
if (tokens[i].type == ONE) {
- if (i == 0 && token_count > 1 && tokens[1].type == SLASH) {
- exp_sign = -1.0;
- i += 2;
- continue;
- } else {
- goto error;
- }
+ if (i > 0) goto error;
+ if (token_count <= 1) goto error;
+ if (tokens[1].type != SLASH) goto error;
+
+ exp_sign = -1.0;
+ i += 2;
+ continue;
}
if (tokens[i].type == SLASH) {
- if (exp_sign > 0) {
- exp_sign = -1.0;
- i += 1;
- continue;
- } else {
- goto error;
- }
+ if (exp_sign < 0) goto error;
+ exp_sign = -1.0;
+ i += 1;
+ continue;
}
if (tokens[i].type != NAME) goto error;
- double unit_value = resolve_unit_name(tokens[i].value.str);
- if(unit_value == 0.0) goto error;
+ double unit_value = unith_parse_unit(tokens[i].value.str);
+ if (unit_value == 0.0) goto error;
- if (token_count <= i+1 || tokens[i + 1].type != EXP) {
+ if (token_count <= i + 1 || tokens[i + 1].type != EXP) {
value *= pow(unit_value, exp_sign);
i += 1;
continue;
}
- if (token_count <= i+2 || tokens[i + 2].type != NUMBER) goto error;
+ if (token_count <= i + 2 || tokens[i + 2].type != NUMBER)
+ goto error;
value *= pow(unit_value, exp_sign * tokens[i + 2].value.num);
i += 3;