From a344af24f685dc124489b76e38d56b76ab7bf235 Mon Sep 17 00:00:00 2001 From: Joseph Elliott Hand Date: Fri, 1 May 2026 17:42:34 -1000 Subject: Refactoring and code style improvements Signed-off-by: Joseph Elliott Hand --- .clang-format | 1 + unit.h | 208 +++++++++++++++++++++++++++------------------------------- 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 . */ - + #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 #include +#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; -- cgit v1.2.3