main.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include "sti/sti.h"
  4. #define BASE_UNIT_TYPE_LIST \
  5. X(time) \
  6. X(mass) \
  7. X(distance) \
  8. X(heat) \
  9. X(current) \
  10. X(substance) \
  11. X(luminosity) \
  12. #define SYSTEM_LIST \
  13. X(universal, Universal) \
  14. X(soy, SI) \
  15. X(based, Imperial) \
  16. #define UNIVERSAL_UNITS \
  17. X(second, time, s, 1s) \
  18. X(ampere, current, A, 1A) \
  19. X(mole, substance, mol, 1mol) \
  20. #define SOY_UNITS \
  21. X(gram, mass, g, 1g) \
  22. X(meter, distance, m, 1m) \
  23. X(kelvin, heat, K, 1K) \
  24. X(candela, luminosity, cd, 1cd) \
  25. #define BASED_UNITS \
  26. X(pound, mass, lb) \
  27. X(inch, distance, in) \
  28. X(rankine, heat, R) \
  29. X(candepower, luminosity, cp) \
  30. #define DERIVED_UNITS \
  31. X(watt, universal, W, 1000 g * m^2 * s^-3) \
  32. X(volt, universal, V, 1000 g * m^2 * s^-3 * A^-1) \
  33. X(newton, soy, N, 1000 g * m / s^2) \
  34. X(coulomb, universal, C, 1 A * s) \
  35. X(joule, soy, J, 1000 g * m^2 * s^-2) \
  36. enum {
  37. #define X(z, ...) z,
  38. BASE_UNIT_TYPE_LIST
  39. #undef X
  40. };
  41. enum {
  42. #define X(z, ...) z,
  43. SYSTEM_LIST
  44. #undef X
  45. };
  46. enum {
  47. #define X(z, ...) z,
  48. UNIVERSAL_UNITS
  49. SOY_UNITS
  50. BASED_UNITS
  51. DERIVED_UNITS
  52. #undef X
  53. };
  54. char* base_unit_type_names[] = {
  55. #define X(x, ...) [x] = #x,
  56. BASE_UNIT_TYPE_LIST
  57. #undef X
  58. };
  59. int unit_base_types[] = {
  60. #define X(u, bt, ...) [u] = bt,
  61. UNIVERSAL_UNITS
  62. SOY_UNITS
  63. BASED_UNITS
  64. #undef X
  65. };
  66. typedef struct unit {
  67. char* name;
  68. double amt;
  69. unsigned char base_unit[7];
  70. char power[7];
  71. } unit_t;
  72. void unit_multiply(unit_t* a, unit_t* b, unit_t* out) {
  73. out->amt = a->amt * b->amt;
  74. for(int i = 0; i < 7; i++) {
  75. out->power[i] = a->power[i] + b->power[i];
  76. }
  77. // todo: look up name, if it exists
  78. }
  79. struct {
  80. char* name;
  81. int system;
  82. char* abbr;
  83. char* def;
  84. } derived_unit_list[] = {
  85. #define X(name, system, abbr, def) [name] = {#name, system, #abbr, #def},
  86. DERIVED_UNITS
  87. #undef X
  88. };
  89. void unit_parse(char* s, unit_t* out) {
  90. char* e = NULL;
  91. out->amt = strtod(s, &e);
  92. int last_unit = -1;
  93. int last_power = 1;
  94. int last_power_sign = 1;
  95. int invert = 1;
  96. for(; *e; e++) {
  97. switch(*e) {
  98. case 's': last_unit = second; break;
  99. case 'g': last_unit = gram; break;
  100. case 'm':
  101. if(e[1] == 'o' && e[2] == 'l') last_unit = mole;
  102. else last_unit = meter;
  103. break;
  104. case 'K': last_unit = kelvin; break;
  105. case 'A': last_unit = ampere; break;
  106. case 'c':
  107. if(e[1] == 'd') last_unit = candela;
  108. break;
  109. case '^':
  110. last_power = 0;
  111. break;
  112. case '-':
  113. last_power_sign = -1;
  114. break;
  115. case '0':
  116. case '1':
  117. case '2':
  118. case '3':
  119. case '4':
  120. case '5':
  121. case '6':
  122. case '7':
  123. case '8':
  124. case '9':
  125. last_power = last_power * 10 + (*e - '0');
  126. break;
  127. case '*':
  128. if(last_unit >= 0) {
  129. out->power[unit_base_types[last_unit]] += last_power * last_power_sign * invert;
  130. last_unit = -1;
  131. last_power = 1;
  132. last_power_sign = 1;
  133. }
  134. break;
  135. case '/':
  136. if(last_unit >= 0) {
  137. out->power[unit_base_types[last_unit]] += last_power * last_power_sign * invert;
  138. last_unit = -1;
  139. last_power = 1;
  140. last_power_sign = 1;
  141. }
  142. invert *= -1;
  143. break;
  144. }
  145. }
  146. if(last_unit >= 0) {
  147. out->power[unit_base_types[last_unit]] += last_power * last_power_sign * invert;
  148. }
  149. }
  150. int main(int argc, char* argv[]) {
  151. unit_t n = {};
  152. unit_parse(derived_unit_list[volt].def, &n);
  153. printf("%f\n", n.amt);
  154. for(int x = 0; x < 7; x++) {
  155. printf("%s ^%d\n", base_unit_type_names[x], (int)n.power[x]);
  156. }
  157. return 0;
  158. }