pico-scale
mass.c
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2022 Daniel Robertson
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.
22 
23 #include <assert.h>
24 #include <float.h>
25 #include <math.h>
26 #include <stdbool.h>
27 #include <stddef.h>
28 #include <stdio.h>
29 #include "pico/types.h"
30 #include "../include/mass.h"
31 
32 const char* const mass_unit_to_string(const mass_unit_t u) {
33  return MASS_NAMES[(uint)u];
34 }
35 
36 const double* const mass_unit_to_ratio(const mass_unit_t u) {
37  return &MASS_RATIOS[(uint)u];
38 }
39 
41  const double* const fromAmount,
42  double* const toAmount,
43  const mass_unit_t fromUnit,
44  const mass_unit_t toUnit) {
45 
46  assert(fromAmount != NULL);
47  assert(toAmount != NULL);
48 
49  if(fromUnit == toUnit) {
50  *toAmount = *fromAmount;
51  }
52  else if(toUnit == mass_ug) {
53  *toAmount = *fromAmount * *mass_unit_to_ratio(fromUnit);
54  }
55  else if(fromUnit == mass_ug) {
56  *toAmount = *fromAmount / *mass_unit_to_ratio(toUnit);
57  }
58  else {
59  mass_convert(fromAmount, toAmount, toUnit, mass_ug);
60  }
61 
62 }
63 
64 void mass_init(
65  mass_t* const m,
66  const mass_unit_t unit,
67  const double val) {
68 
69  assert(m != NULL);
70 
71  mass_convert(&val, &m->ug, unit, mass_ug);
72  m->unit = unit;
73 
74 }
75 
77  const mass_t* const m,
78  double* const val) {
79 
80  assert(m != NULL);
81  assert(val != NULL);
82 
83  mass_convert(&m->ug, val, mass_ug, m->unit);
84 
85 }
86 
87 void mass_add(
88  const mass_t* const lhs,
89  const mass_t* const rhs,
90  mass_t* const res) {
91 
92  assert(lhs != NULL);
93  assert(rhs != NULL);
94  assert(res != NULL);
95 
96  res->ug = lhs->ug + rhs->ug;
97  res->unit = lhs->unit;
98 
99 }
100 
101 void mass_sub(
102  const mass_t* const lhs,
103  const mass_t* const rhs,
104  mass_t* const res) {
105 
106  assert(lhs != NULL);
107  assert(rhs != NULL);
108  assert(res != NULL);
109 
110  res->ug = lhs->ug - rhs->ug;
111  res->unit = lhs->unit;
112 
113 }
114 
115 void mass_mul(
116  const mass_t* const lhs,
117  const mass_t* const rhs,
118  mass_t* const res) {
119 
120  assert(lhs != NULL);
121  assert(rhs != NULL);
122  assert(res != NULL);
123 
124  res->ug = lhs->ug * rhs->ug;
125  res->unit = lhs->unit;
126 
127 }
128 
129 bool mass_div(
130  const mass_t* const lhs,
131  const mass_t* const rhs,
132  mass_t* const res) {
133 
134  assert(lhs != NULL);
135  assert(rhs != NULL);
136  assert(res != NULL);
137 
138  //if ~0; protect against div / 0
139  if(fabs(rhs->ug) < DBL_EPSILON) {
140  return false;
141  }
142 
143  res->ug = lhs->ug / rhs->ug;
144  res->unit = lhs->unit;
145  return true;
146 
147 }
148 
150  mass_t* const self,
151  const mass_t* const rhs) {
152  mass_add(self, rhs, self);
153 }
154 
156  mass_t* const self,
157  const mass_t* const rhs) {
158  mass_sub(self, rhs, self);
159 }
160 
162  mass_t* const self,
163  const mass_t* const rhs) {
164  mass_mul(self, rhs, self);
165 }
166 
168  mass_t* const self,
169  const mass_t* const rhs) {
170  return mass_div(self, rhs, self);
171 }
172 
173 bool mass_eq(
174  const mass_t* const lhs,
175  const mass_t* const rhs) {
176 
177  assert(lhs != NULL);
178  assert(rhs != NULL);
179 
180  //if ~==; if approx ~0
181  return fabs(lhs->ug - rhs->ug) < DBL_EPSILON;
182 
183 }
184 
185 bool mass_neq(
186  const mass_t* const lhs,
187  const mass_t* const rhs) {
188 
189  assert(lhs != NULL);
190  assert(rhs != NULL);
191 
192  return !mass_eq(lhs, rhs);
193 
194 }
195 
196 bool mass_lt(
197  const mass_t* const lhs,
198  const mass_t* const rhs) {
199 
200  assert(lhs != NULL);
201  assert(rhs != NULL);
202 
203  return lhs->ug < rhs->ug;
204 
205 }
206 
207 bool mass_gt(
208  const mass_t* const lhs,
209  const mass_t* const rhs) {
210 
211  assert(lhs != NULL);
212  assert(rhs != NULL);
213 
214  return mass_lt(rhs, lhs);
215 
216 }
217 
219  const mass_t* const lhs,
220  const mass_t* const rhs) {
221 
222  assert(lhs != NULL);
223  assert(rhs != NULL);
224 
225  return !mass_gt(lhs, rhs);
226 
227 }
228 
230  const mass_t* const lhs,
231  const mass_t* const rhs) {
232 
233  assert(lhs != NULL);
234  assert(rhs != NULL);
235 
236  return !mass_lt(lhs, rhs);
237 
238 }
239 
240 
242  const mass_t* const m,
243  char* const buff) {
244 
245  assert(m != NULL);
246  assert(buff != NULL);
247 
248  double n; //value
249  mass_get_value(m, &n);
250  double i; //int part; discard
251  const double f = fabs(modf(n, &i)); //frac part
252  uint d = 0; //decimal count
253 
254  //if less than the epsilon, then it's ~0
255  if(f >= DBL_EPSILON) {
256  d = (uint)fmax(0, ceil(1 - log10(f)));
257  }
258 
259  return snprintf(
260  buff,
262  "%01.*f %s", //format
263  d, //how many decimals
264  n, //the value
265  mass_unit_to_string(m->unit)); //suffix (ie. "kg")
266 
267 }
const double *const mass_unit_to_ratio(const mass_unit_t u)
Returns a pointer to a double with the number of micrograms per unit.
Definition: mass.c:36
bool mass_diveq(mass_t *const self, const mass_t *const rhs)
Divide self by rhs, returns false if rhs is 0.
Definition: mass.c:167
int mass_to_string(const mass_t *const m, char *const buff)
Fills buff with the string representation of the mass_t. eg. "32.4762 mg".
Definition: mass.c:241
bool mass_lteq(const mass_t *const lhs, const mass_t *const rhs)
Returns true if lhs is less than or equal to rhs.
Definition: mass.c:218
const char *const mass_unit_to_string(const mass_unit_t u)
Returns a pointer to char with the textual representation of the unit.
Definition: mass.c:32
void mass_add(const mass_t *const lhs, const mass_t *const rhs, mass_t *const res)
Add lhs to rhs and store result in res.
Definition: mass.c:87
bool mass_gteq(const mass_t *const lhs, const mass_t *const rhs)
Returns true if lhs is greater than or equal to rhs.
Definition: mass.c:229
void mass_subeq(mass_t *const self, const mass_t *const rhs)
Subtract rhs from self.
Definition: mass.c:155
void mass_mul(const mass_t *const lhs, const mass_t *const rhs, mass_t *const res)
Multiply lhs by rhs and store result in res.
Definition: mass.c:115
void mass_convert(const double *const fromAmount, double *const toAmount, const mass_unit_t fromUnit, const mass_unit_t toUnit)
Converts a floating point value from one unit to another.
Definition: mass.c:40
bool mass_gt(const mass_t *const lhs, const mass_t *const rhs)
Returns true if lhs is greater than rhs.
Definition: mass.c:207
void mass_init(mass_t *const m, const mass_unit_t unit, const double val)
Initialises a mass_t with the given unit and value.
Definition: mass.c:64
bool mass_neq(const mass_t *const lhs, const mass_t *const rhs)
Returns true if lhs does not equal rhs.
Definition: mass.c:185
void mass_muleq(mass_t *const self, const mass_t *const rhs)
Multiply self by rhs.
Definition: mass.c:161
void mass_addeq(mass_t *const self, const mass_t *const rhs)
Add rhs to self.
Definition: mass.c:149
void mass_sub(const mass_t *const lhs, const mass_t *const rhs, mass_t *const res)
Substract rhs from lhs and store result in res.
Definition: mass.c:101
bool mass_eq(const mass_t *const lhs, const mass_t *const rhs)
Returns true if lhs equals rhs.
Definition: mass.c:173
bool mass_div(const mass_t *const lhs, const mass_t *const rhs, mass_t *const res)
Divide lhs by rhs and store result in res, returns false if rhs is 0.
Definition: mass.c:129
bool mass_lt(const mass_t *const lhs, const mass_t *const rhs)
Returns true if lhs is less than rhs.
Definition: mass.c:196
void mass_get_value(const mass_t *const m, double *const val)
Sets val to the value representing the mass_t according to its unt.
Definition: mass.c:76
static const double MASS_RATIOS[]
Definition: mass.h:33
mass_unit_t
Definition: mass.h:64
@ mass_ug
Definition: mass.h:65
static const char *const MASS_NAMES[]
Definition: mass.h:46
static const size_t MASS_TO_STRING_BUFF_SIZE
Definition: mass.h:59
Definition: mass.h:93
double ug
Definition: mass.h:94
mass_unit_t unit
Definition: mass.h:95