1 /*
2  * Copyright (c) 2003-2007 Hypertriton, Inc. <http://hypertriton.com/>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
23  * USE OF THIS SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include <agar/core/core.h>
27 #include <agar/gui/units.h>
28 #include <agar/gui/gui_math.h>
29 
30 #include <string.h>
31 
32 /* #define ASTRONOMICAL_UNITS */
33 /* #define HISTORICAL_UNITS */
34 
35 const char *agUnitGroupNames[] = {
36 	N_("Identity"),
37 	N_("Length"),
38 	N_("Angle"),
39 	N_("Video"),
40 	N_("Area"),
41 	N_("Volume"),
42 	N_("Velocity"),
43 	N_("Mass"),
44 	N_("Time"),
45 	N_("Electrical current"),
46 	N_("Temperature"),
47 	N_("Substance amount"),
48 	N_("Light"),
49 	N_("Power"),
50 	N_("Electromotive force"),
51 	N_("Electrical resistance"),
52 	N_("First-order resistance coefficient"),
53 	N_("Second-order resistance coefficient"),
54 	N_("Capacitance"),
55 	N_("Inductance"),
56 	N_("Frequency"),
57 	N_("Pressure"),
58 	N_("Vacuum"),
59 	N_("Percentage"),
60 	N_("K units (MOSFET)"),
61 	NULL
62 };
63 const AG_Unit *agUnitGroups[] = {
64 	agIdentityUnit,
65 	agLengthUnits,
66 	agAngleUnits,
67 	agVideoUnits,
68 	agAreaUnits,
69 	agVolumeUnits,
70 	agSpeedUnits,
71 	agMassUnits,
72 	agTimeUnits,
73 	agCurrentUnits,
74 	agTemperatureUnits,
75 	agSubstanceAmountUnits,
76 	agEnergyPerSubstanceAmountUnits,
77 	agLightUnits,
78 	agPowerUnits,
79 	agEMFUnits,
80 	agResistanceUnits,
81 	agResistanceTC1Units,
82 	agResistanceTC2Units,
83 	agCapacitanceUnits,
84 	agInductanceUnits,
85 	agFrequencyUnits,
86 	agPressureUnits,
87 	agVacuumUnits,
88 	agPercentageUnits,
89 	agKUnits,
90 	agResistivityUnits,
91 	agThermalConductivityUnits,
92 	agThermalExpansionUnits,
93 	agDensityUnits,
94 };
95 const int agnUnitGroups = sizeof(agUnitGroups) / sizeof(agUnitGroups[0]);
96 
97 /*
98  * Return the unit in the given group with a matching key.
99  * If key=NULL, return the base unit.
100  */
101 const AG_Unit *
AG_FindUnit(const char * key)102 AG_FindUnit(const char *key)
103 {
104 	int i;
105 
106 	for (i = 0; i < agnUnitGroups; i++) {
107 		const AG_Unit *group = agUnitGroups[i];
108 		const AG_Unit *unit;
109 
110 		for (unit = &group[0]; unit->key != NULL; unit++) {
111 			if (key == NULL) {
112 				if (unit->divider == 1)
113 					return (unit);
114 			} else {
115 				if (strcmp(unit->key, key) == 0)
116 					return (unit);
117 			}
118 		}
119 	}
120 	AG_SetError(_("No such unit: %s"), key);
121 	return (NULL);
122 }
123 
124 /* Return the unit which yields the number with the least figures. */
125 const AG_Unit *
AG_BestUnit(const AG_Unit ugroup[],double n)126 AG_BestUnit(const AG_Unit ugroup[], double n)
127 {
128 	const AG_Unit *unit, *bestunit = NULL;
129 	double smallest = HUGE_VAL;
130 	double diff;
131 
132 	if (n == 0) {
133 		goto defunit;
134 	}
135 	for (unit = &ugroup[0]; unit->key != NULL; unit++) {
136 		if (n/unit->divider >= 1.0) {
137 			diff = Fabs(n-unit->divider);
138 			if (diff < smallest) {
139 				smallest = diff;
140 				bestunit = unit;
141 			}
142 		}
143 	}
144 	if (bestunit == NULL) {
145 		goto defunit;
146 	}
147 	return (bestunit);
148 defunit:
149 	for (unit = &ugroup[0]; unit->key != NULL; unit++) {
150 		if (unit->divider == 1.0)
151 			break;
152 	}
153 	return (unit);
154 }
155 
156 /* Format a number using the unit most suited to its magnitude. */
157 int
AG_UnitFormat(double n,const AG_Unit ugroup[],char * buf,size_t len)158 AG_UnitFormat(double n, const AG_Unit ugroup[], char *buf, size_t len)
159 {
160 	const AG_Unit *ubest;
161 
162 	ubest = AG_BestUnit(ugroup, n);
163 	return (Snprintf(buf, len, "%.2f%s", AG_Base2Unit(n, ubest),
164 	    ubest->abbr[0] != '\0' ? ubest->abbr : ubest->key));
165 }
166 
167 /* Default unit (identity) */
168 const AG_Unit agIdentityUnit[] = {
169 	{ "identity", "", "",	1.0, NULL },
170 	{ NULL,	NULL, NULL,	0, NULL }
171 };
172 
173 /* Units of length/distance */
174 const AG_Unit agLengthUnits[] = {
175 	{ "Ang", "\xc3\x85", N_("\xc3\x85ngstroms"), 1e-10,	NULL },
176 	{ "fm", "", N_("Femtometres"),		1e-15,		NULL },
177 	{ "pm", "", N_("Picometres"),		1e-12,		NULL },
178 	{ "nm", "", N_("Nanometres"),		1e-9,		NULL },
179 	{ "um", "\xc2\xb5", N_("Microns"),	1e-6,		NULL },
180 	{ "mil", "", N_("Mils"),		25e-6,		NULL },
181 	{ "mm", "", N_("Millimeters"),		1e-3,		NULL },
182 	{ "in", "", N_("Inches"),		0.0254,		NULL },
183 	{ "cm",	"", N_("Centimeters"),		1e-2,		NULL },
184 	{ "dm",	"", N_("Decimeters"),		0.1,		NULL },
185 	{ "ft",	"", N_("Feet"),			0.3048,		NULL },
186 	{ "yd", "", N_("Yards"),		0.9144,		NULL },
187 	{ "m", "", N_("Meters"),		1.0,		NULL },
188 	{ "km", "", N_("Kilometers"),		1000,		NULL },
189 	{ "mi", "", N_("Miles"),		1609.344,	NULL },
190 #ifdef ASTRONOMICAL_UNITS
191 	{ "A.U", "", N_("Astronomical units"),	159598073000.0,		NULL },
192 	{ "L.Y", "", N_("Light years"),		946075309081900.0,	NULL },
193 	{ "P.S", "", N_("Parsecs"),		3085678e10,		NULL },
194 #endif
195 #ifdef HISTORICAL_UNITS
196 	{ "N.M", "", N_("Nautical miles"),	1852,		NULL },
197 	{ "N.L", "", N_("Nautical leagues"),	5556,		NULL },
198 	{ "lnk", "", N_("Links"),		0.201168,	NULL },
199 	{ "span", "", N_("Spans"),		0.2286,		NULL },
200 	{ "cbt", "", N_("Cubits"),		0.4572,		NULL },
201 	{ "var", "", N_("Varas"),		0.846668,	NULL },
202 	{ "fh", "", N_("Fathoms"),		1.8288,		NULL },
203 	{ "rod", "", N_("Rods"),		5.0292,		NULL },
204 	{ "cha", "", N_("Chains"),		20.1168,	NULL },
205 	{ "fur", "", N_("Furlongs"),		201.167981,	NULL },
206 	{ "cbl", "", N_("Cable lengths"),	219.456,	NULL },
207 #endif
208 	{ NULL,	NULL, NULL,			0, NULL }
209 };
210 
211 /* Units of angle */
212 const AG_Unit agAngleUnits[] = {
213 	{ "rad", "", N_("Radians"),		1.0, NULL },
214 	{ "deg", "\xc2\xb0", N_("Degrees"),	0.01745329251994329577, NULL },
215 	{ "rev", "", N_("Revolutions"),		6.28318530717958647692, NULL },
216 	{ "grad", "", N_("Grads"),		0.01570796326794896619, NULL },
217 	{ "point", "", N_("Points"),		0.19634954084936207740, NULL },
218 	{ "brad", "", N_("Binary degrees"),	0.02454369260617025968, NULL },
219 	{ "HA", "", N_("Hour angle"),		0.26179938779914943654, NULL },
220 	{ NULL,	NULL, NULL,			0, NULL }
221 };
222 
223 /* Units of length/distance on a raster display. */
224 /* TODO resolution-specific functions */
225 const AG_Unit agVideoUnits[] = {
226 	{ "px", "", N_("Pixels"),		1.0, NULL },
227 	{ "kpx", "", N_("Kilopixels"),		1e3, NULL },
228 	{ "Mpx", "", N_("Megapixels"),		1e6, NULL },
229 	{ NULL,	NULL, NULL,			0, NULL }
230 };
231 
232 /* Units of area (SI derived) */
233 const AG_Unit agAreaUnits[] = {
234 	{ "um^2", "\xc2\xb5\xc2\xb2", N_("Square micrometers"),	1e-6, NULL },
235 	{ "mm^2", "mm\xc2\xb2",	N_("Square millimeters"),	1e-3, NULL },
236 	{ "cm^2", "cm\xc2\xb2",	N_("Square centimeters"),	1e-2, NULL },
237 	{ "in^2", "in\xc2\xb2",	N_("Square inches"),		0.0254,	NULL },
238 	{ "ft^2", "ft\xc2\xb2",	N_("Square feet"),		0.3048,	NULL },
239 	{ "yd^2", "yd\xc2\xb2",	N_("Square yards"),		0.9144,	NULL },
240 	{ "m^2", "m\xc2\xb2",	N_("Square meters"),		1.0, NULL },
241 	{ "km^2", "km\xc2\xb2",	N_("Square kilometers"),	1000, NULL },
242 	{ "mi^2", "mi\xc2\xb2",	N_("Square miles"),		1609.35, NULL },
243 	{ NULL, NULL, NULL,					0, NULL }
244 };
245 
246 /* Units of volume (SI derived) */
247 const AG_Unit agVolumeUnits[] = {
248 	{ "um^3", "\xc2\xb5m\xc2\xb3", N_("Cubic micrometers"),	1e-6, NULL },
249 	{ "mm^3", "mm\xc2\xb3",	N_("Cubic millimeters"),	1e-3, NULL },
250 	{ "cm^3", "cm\xc2\xb3",	N_("Cubic centimeters"),	1e-2, NULL },
251 	{ "in^3", "in\xc2\xb3",	N_("Cubic inches"),		0.0254, NULL },
252 	{ "ft^3", "ft\xc2\xb3",	N_("Cubic feet"),		0.3048,	NULL },
253 	{ "yd^3", "yd\xc2\xb3",	N_("Cubic yards"),		0.9144, NULL },
254 	{ "m^3", "m\xc2\xb3", N_("Cubic meters"),		1.0, NULL },
255 	{ "km^3", "km\xc2\xb3",	N_("Cubic kilometers"),		1e3, NULL },
256 	{ "mi^3", "mi\xc2\xb3",	N_("Cubic miles"),		1609.35, NULL },
257 	{ NULL, NULL, NULL,					0, NULL }
258 };
259 
260 /* Units of speed/velocity (SI derived) */
261 const AG_Unit agSpeedUnits[] = {
262 	{ "um/s", "\xc2\xb5m/s", N_("Micrometers per second"),	1e-6, NULL },
263 	{ "mm/s", "", N_("Millimeters per second"),		1e-3, NULL },
264 	{ "cm/s", "", N_("Centimeters per second"),		1e-2, NULL },
265 	{ "in/s", "", N_("Inches per second"),			0.0254, NULL },
266 	{ "ft/s", "", N_("Feet per second"),			0.3048,	NULL },
267 	{ "yd/s", "", N_("Yards per second"),			0.9144,	NULL },
268 	{ "m/s", "", N_("Meters per second"),			1.0, NULL },
269 	{ "km/s", "", N_("Kilometers per second"),		1e3, NULL },
270 	{ "mi/s", "", N_("Miles per second"),			1609.35, NULL },
271 	{ NULL, NULL, NULL,					0, NULL }
272 };
273 
274 /* Units of weight */
275 const AG_Unit agMassUnits[] = {
276 	{ "ug", "\xc2\xb5g", N_("Micrograms"),	1e-6,			NULL },
277 	{ "mg", "", N_("Milligrams"),		1e-3,			NULL },
278 	{ "cg", "", N_("Centigrams"),		1e-2,			NULL },
279 	{ "dg", "", N_("Decigrams"),		1e-1,			NULL },
280 	{ "g", "", N_("Grams"),			1.0,			NULL },
281 	{ "oz", "", N_("Ounces [comm]"),	28.349,			NULL },
282 	{ "lb", "", N_("Pounds [comm]"),	453.59,			NULL },
283 	{ "kg", "", N_("Kilograms"),		1e3,			NULL },
284 	{ "t(s)", "", N_("Tons [short]"),	907200,			NULL },
285 	{ "t", "", N_("Tons [metric]"),		1e6,			NULL },
286 	{ "t(l)", "", N_("Tons [long]"),	1016064,		NULL },
287 #ifdef HISTORICAL_UNITS
288 	{ "grain", "", "Grains",		0.0648,			NULL },
289 	{ "carat", "", "Carats [troy]",		0.2,			NULL },
290 	{ "dram(a)", "", "Drams [apot]",	3.888,			NULL },
291 	{ "oz(t)", "", N_("Ounces [troy]"),	31.104,			NULL },
292 	{ "lb(t)", "", N_("Pounds [troy]"),	373.248,		NULL },
293 	{ "scruple", "", "Scruples [apot]",	1.296,			NULL },
294 	{ "pennywt", "", "Pennyweights",	1.5552,			NULL },
295 	{ "dram", "", "Drams",			1.771875,		NULL },
296 	{ "poundal", "", "Poundals",		14.086956521739,	NULL },
297 	{ "stone", "", "Stones",		6530.40,		NULL },
298 	{ "quarter", "", "Quarters",		11340,			NULL },
299 	{ "slug", "", "Slugs",			14605.92,		NULL },
300 	{ "100wt", "", "100 weights",		45360,			NULL },
301 	{ "batman", "", "Batmans",		16e6,			NULL },
302 #endif
303 	{ NULL, NULL, NULL,				0, NULL }
304 };
305 
306 /* Units of time */
307 const AG_Unit agTimeUnits[] = {
308 	{ "ns", "", N_("Nanoseconds"),			1e-9, NULL },
309 	{ "us", "\xc2\xb5s", N_("Microseconds"),	1e-6, NULL },
310 	{ "ms", "", N_("Milliseconds"),			1e-3, NULL },
311 	{ "sec", "", N_("Seconds"),			1.0, NULL },
312 	{ "min", "", N_("Minutes"),			60, NULL },
313 	{ "hr", "", N_("Hours"),			3600, NULL },
314 	{ "day", "", N_("Days"),			86400, NULL },
315 	{ "w(p)", "\xce\x9a\x64", N_("Weeks [POEE]"),	432000, NULL },
316 	{ "wk", "", N_("Weeks"),			604800,	NULL },
317 	{ "m(p)", "\xce\x9am", N_("Months [POEE]"),	6307200, NULL },
318 	{ "yr", "", N_("Years"),			31104000, NULL },
319 	{ NULL,	NULL, NULL,				0, NULL }
320 };
321 
322 /* Units of electrical current */
323 const AG_Unit agCurrentUnits[] = {
324 	{ "pA", "", N_("Picoamperes"),			1e-12, NULL },
325 	{ "nA", "", N_("Nanoamperes"),			1e-9, NULL },
326 	{ "uA", "\xc2\xb5\x41", N_("Microamperes"),	1e-6, NULL },
327 	{ "mA", "", N_("Milliamperes"),			1e-3, NULL },
328 	{ "A", "", N_("Amperes"),			1.0, NULL },
329 	{ "kA", "", N_("Kiloamperes"),			1e3, NULL },
330 	{ "MA", "", N_("Megaamperes"),			1e6, NULL },
331 	{ NULL, NULL, NULL,				0, NULL }
332 };
333 
334 const AG_Unit agTemperatureUnits[] = {
335 	{ "degC", "\xc2\xb0\x43", N_("Degrees Celsius"),   0, AG_UnitCelsius },
336 	{ "degF", "\xc2\xb0\x46", N_("Degrees Farenheit"),0, AG_UnitFahrenheit},
337 	{ "uk", "\xc2\xb5k", "Microkelvins",			1e-6, NULL },
338 	{ "mk", "", "Millikelvins",				1e-3, NULL },
339 	{ "k", "", "Kelvins",					1.0, NULL },
340 	{ "kk",	"", "Kilokelvins",				1e3, NULL },
341 	{ "Mk",	"", N_("Megakelvins"),				1e6, NULL },
342 	{ NULL,	NULL, NULL,					0, NULL }
343 };
344 
345 /* Units of substance amount */
346 const AG_Unit agSubstanceAmountUnits[] = {
347 	{ "pmol", "", "Picomoles",			1e-12, NULL },
348 	{ "umol", "\xc2\xb5mol", "Micromoles",		1e-6, NULL },
349 	{ "mmol", "", "Millimoles",			1e-3, NULL },
350 	{ "mol", "", "Moles",				1.0, NULL },
351 	{ "kmol", "", "Kilomoles",			1e3, NULL },
352 	{ "Mmol", "", N_("Megamoles"),			1e6, NULL },
353 	{ NULL,	NULL, NULL,				0, NULL }
354 };
355 
356 /* Units of energy per substance amount */
357 const AG_Unit agEnergyPerSubstanceAmountUnits[] = {
358 	{ "J/mol", "", "Joules per mole",		1e-3, NULL },
359 	{ "kJ/mol", "", "Kilojoules per mole",		1.0, NULL },
360 	{ "MJ/mol", "", "Megajoules per mole",		1e3, NULL },
361 	{ NULL,	NULL, NULL,				0, NULL }
362 };
363 
364 /* Units of molar heat capacity */
365 const AG_Unit agMolarHeatCapacityUnits[] = {
366 	{ "J/mol.k", "J/mol\xc2\xb7k", "Joules per mole kelvin",	1.0, NULL },
367 	{ "kJ/mol.k", "kJ/mol\xc2\xb7k", "Kilojoules per mole kelvin",	1e3, NULL },
368 	{ "MJ/mol.k", "MJ/mol\xc2\xb7k", "Megajoules per mole kelvin",	1e6, NULL },
369 	{ NULL,	NULL, NULL,						0, NULL }
370 };
371 
372 /* Units of light measurement */
373 const AG_Unit agLightUnits[] = {
374 	{ "ucd", "\xc2\xb5\x63\x64", "Microcandelas",		1e-6, NULL },
375 	{ "mcd", "", "Millicandelas",				1e-3, NULL },
376 	{ "cd", "", "Candelas",					1.0, NULL },
377 	{ "kcd", "", "Kilocandelas",				1e3, NULL },
378 	{ "Mcd", "", N_("Megacandelas"),			1e6, NULL },
379 	{ NULL, NULL, NULL,					0, NULL }
380 };
381 
382 /* Units of power */
383 const AG_Unit agPowerUnits[] = {
384 	{ "uW", "\xc2\xb5W", "Microwatts",	1e-6, NULL },
385 	{ "mW", "", "Milliwatts",		1e-3, NULL },
386 	{ "BTU/h", "", "BTU/hr",		0.292875, NULL },
387 	{ "f-lb/s", "", N_("Foot-lbs/sec"),	1.355818, NULL },
388 	{ "W", "", "Watts",			1.0, NULL },
389 	{ "kC/m", "", "Kilocalories/min",	69.733, NULL },
390 	{ "HP", "", N_("Horsepower"),		746, NULL },
391 	{ "kW", "", "Kilowatts",		1e3, NULL },
392 	{ "kC/s", "", "Kilocalories/sec",	4183.98, NULL },
393 	{ "MW", "", N_("Megawatts"),		1e6, NULL },
394 	{ "GW", "", "Gigawatts",		1e9, NULL },
395 	{ NULL, NULL, NULL,			0, NULL }
396 };
397 
398 /* Units of electromotive force */
399 const AG_Unit agEMFUnits[] = {
400 	{ "uV", "\xc2\xb5V", "Microvolts",	1e-6, NULL },
401 	{ "mV", "", "Millivolts",		1e-3, NULL },
402 	{ "V", "", "Volts",			1.0, NULL },
403 	{ "kV", "", "Kilovolts",		1e3, NULL },
404 	{ "MV", "", N_("Megavolts"),		1e6, NULL },
405 	{ NULL, NULL, NULL,			0, NULL }
406 };
407 
408 /* Units of electrical resistance */
409 const AG_Unit agResistanceUnits[] = {
410 	{ "uohm", "\xc2\xb5\xce\xa9", "Micro-ohms",	1e-6, NULL },
411 	{ "mohm", "m\xce\xa9", "Milliohms",		1e-3, NULL },
412 	{ "ohm", "\xce\xa9", "Ohms",			1.0, NULL },
413 	{ "kohm", "k\xce\xa9",	"Kilo-ohms",		1e3, NULL },
414 	{ "Mohm", "M\xce\xa9", N_("Megaohms"),		1e6, NULL },
415 	{ NULL, NULL, NULL,				0, NULL }
416 };
417 
418 /* Units of first order temperature coefficients of resistance. */
419 const AG_Unit agResistanceTC1Units[] = {
420 	{ "mohm/degC", "m\xce\xa9/\xc2\xb0\x43", "Milliohms per \xc2\xb0\x43",
421 	  1e-3, NULL},
422 	{ "ohms/degC", "\xce\xa9/\xc2\xb0\x43", "Ohms per\xc2\xb0\x43",
423 	  1.0, NULL},
424 	{ NULL, NULL, NULL, 0, NULL }
425 };
426 
427 /* Units of second order temperature coefficients of resistance. */
428 const AG_Unit agResistanceTC2Units[] = {
429 	{ "mohm/degC^2", "m\xce\xa9/\xc2\xb0\x43\xc2\xb2",
430 	  "Milliohms per \xc2\xb0\x43\xc2\xb2",
431 	  1e-3, NULL},
432 	{ "ohm/degC^2", "\xce\xa9/\xc2\xb0\x43\xc2\xb2",
433 	  "Ohms per \xc2\xb0\x43\xc2\xb2",
434 	  1.0, NULL},
435 	{ NULL, NULL, NULL, 0, NULL }
436 };
437 
438 /* Units of electrical capacitance */
439 const AG_Unit agCapacitanceUnits[] = {
440 	{ "pF", "", "Picofarads",			1e-12, NULL },
441 	{ "nF", "", "Nanofarads",			1e-9, NULL },
442 	{ "uF", "\xc2\xb5\x46",	"Microfarads",		1e-6, NULL },
443 	{ "mF", "", "Millifarads",			1e-3, NULL },
444 	{ "F", "", "Farads",				1.0, NULL },
445 	{ "kF", "", "Kilofarads",			1e3, NULL },
446 	{ NULL,	NULL, NULL,				0, NULL }
447 };
448 
449 /* Units of electrical inductance */
450 const AG_Unit agInductanceUnits[] = {
451 	{ "uH", "\xc2\xb5\x48",	"Microhenries",		1e-6, NULL },
452 	{ "mH", "", "Millihenries",			1e-3, NULL },
453 	{ "H", "", "Henries",				1.0, NULL },
454 	{ "kH", "", "Kilohenries",			1e3, NULL },
455 	{ NULL, NULL, NULL,				0, NULL }
456 };
457 
458 /* Units of frequency */
459 const AG_Unit agFrequencyUnits[] = {
460 	{ "uHz", "\xc2\xb5Hz","Microhertz",	1e-6, NULL },
461 	{ "mHz", "", "Millihertz",		1e-3, NULL },
462 	{ "Hz", "", "Hertz",			1.0, NULL },
463 	{ "kHz", "", "Kilohertz",		1e3, NULL },
464 	{ "MHz", "", N_("Megahertz"),		1e6, NULL },
465 	{ "GHz", "", "Gigahertz",		1e9, NULL },
466 	{ NULL, NULL, NULL,			0, NULL }
467 };
468 
469 /* Units of pressure and stress */
470 const AG_Unit agPressureUnits[] = {
471 	{ "Pa",        "",                "Pascals",			1.0, NULL },
472 	{ "kPa",       "",                "Kilopascals",		1e3, NULL },
473 	{ "MPa",       "",                N_("Megapascals"),		1e6, NULL },
474 	{ "GPa",       "",                "Gigapascals",		1e9, NULL },
475 	{ "bar",       "",                "Bars",			1e5, NULL },
476 	{ "mbar",      "",                "Millibars",			1e2, NULL },
477 	{ "Kg-f/m^2",  "Kg-f/m\xc2\xb2",  N_("Kg-force per m\xc2\xb2"),	9.80665, NULL },
478 	{ "cm H2O",    "cm H\xc2\xb2O",   N_("Centimeters of water"),	98.0665, NULL },
479 	{ "in H2O",    "in H\xc2\xb2O",   N_("Inches of water"),	249.08891, NULL },
480 	{ "cm Hg",     "",                N_("Centimeters of mercury"),	1333.22, NULL },
481 	{ "Ft H2O",    "Ft H\xc2\xb2O",   N_("Feet of water"),   	2989.06692, NULL },
482 	{ "in Hg",     "",                N_("Inches of mercury"),      3386.388, NULL },
483 	{ "m H2O",     "m H\xc2\xb2O",    N_("Meters of water"),	9806.65, NULL },
484 	{ "Kips/in^2", "Kips/in\xc2\xb2", N_("Kips per in\xc2\xb2"),	6894760, NULL },
485 	{ "Atm",       "",                N_("Atmospheres"),		101325, NULL },
486 	{ NULL,	NULL, NULL, 0, NULL }
487 };
488 
489 /* Units of vacuum pressure */
490 const AG_Unit agVacuumUnits[] = {
491 	{ "ubar(V)",       "\xc2\xb5\x62\x61\x72", N_("Microbar"),            0.000750062, NULL },
492 	{ "Pa(V)",         "Pa",               N_("Pascals"),                 0.007500617, NULL },
493 	{ "N/m^2(V)",      "N/m\xc2\xb2",      N_("Newtons per m\xc2\xb2"),   0.007500617, NULL },
494 	{ "mtorr(V)",      "mtorr",            N_("Millitorr"),               0.001, NULL },
495 	{ "micron Hg(V)",  "micron Hg",        N_("Microns of Mercury"),      0.001, NULL },
496 	{ "mbar(V)",       "mbar",             N_("Millibar"),                0.75030012004802, NULL },
497 	{ "torr(V)",       "torr",             N_("Torr"),                    1.0, NULL },
498 	{ "mm Hg(V)",      "mm Hg",            N_("Millimeters of Mercury"),  1.0, NULL },
499 	{ "in H2O(V-4C)",  "in H\xc2\xb2O (4\xc2\xb0\x43)",  N_("Inches of Water (4\xc2\xb0\x43)"), 1.868268641, NULL },
500 	{ "in H2O(V-60F)", "in H\xc2\xb2O (60\xc2\xb0\x46)", N_("Inches of Water (60\xc2\xb0\x46)"), 1.866475993, NULL },
501 	{ "in Hg(V-32F)",  "in Hg (32\xc2\xb0\x46)", N_("Inches of Mercury (32\xc2\xb0\x46)"), 25.399938811, NULL },
502 	{ "in Hg(V-60F)",  "in Hg (60\xc2\xb0\x46)", N_("Inches of Mercury (60\xc2\xb0\x46)"), 25.328457932, NULL },
503 	{ "psi(V)",        "psi",              N_("Pounds per in\xc2\xb2"),   51.714932572, NULL },
504 	{ "at(V)",         "at",               N_("Atmospheres technical"),   735.559240069, NULL },
505 	{ "kg/cm^2(V)",    "kg/cm\xc2\xb2",    N_("Kilograms per cm\xc2\xb2"),735.56454579, NULL },
506 	{ "bar(V)",        "bar",              N_("Bar"),                     750.30012004, NULL },
507 	{ "dynes/cm^2(V)", "dynes/cm\xc2\xb2", N_("Dynes per cm\xc2\xb2"),    750.33012004, NULL },
508 	{ "Atm(V)",        "Atm",              N_("Standard atmospheres"),    760.0, NULL },
509 	{ NULL, NULL, NULL, 0.0, NULL }
510 };
511 
512 const AG_Unit agPercentageUnits[] = {
513 	{ "%", "", N_("Percent"),	1.0, NULL },
514 	{ NULL, NULL, NULL,		0.0, NULL }
515 };
516 
517 /* Units of K (MOSFET parameter) */
518 const AG_Unit agKUnits[] = {
519 	{ "A/V^2", "A/V\xc2\xb2", N_("Amps/Volt\xc2\xb2"), 1.0, NULL },
520 	{ "mA/V^2", "mA/V\xc2\xb2", N_("Milliamps/Volt\xc2\xb2"), 1e-3, NULL },
521 	{ "uA/V^2", "\xc2\xb5\x41/V\xc2\xb2", N_("Microamps/Volt\xc2\xb2"), 1e-6, NULL },
522 	{ NULL, NULL, NULL, 0.0, NULL }
523 };
524 
525 /* Units of resistivity in a material */
526 const AG_Unit agResistivityUnits[] = {
527 	{ "uohm/m", "\xc2\xb5\xce\xa9/m", "Micro-ohms per meter", 1e-6, NULL },
528 	{ "mohm/m", "m\xce\xa9/m", "Milliohms per meter",	1e-3, NULL },
529 	{ "ohm/m", "\xce\xa9/m", "Ohms per meter",		1.0, NULL },
530 	{ "kohm/m", "k\xce\xa9/m", "Kilo-ohms per meter",	1e3, NULL },
531 	{ "Mohm/m", "M\xce\xa9/m", N_("Megaohms per meter"),	1e6, NULL },
532 	{ NULL, NULL, NULL,					0, NULL }
533 };
534 
535 /* Units of thermal conductivity of a material */
536 const AG_Unit agThermalConductivityUnits[] = {
537 	{ "W/m.k", "W/m\xc2\xb7k", "Watts per meter kelvin",	1.0, NULL },
538 	{ NULL, NULL, NULL,					0, NULL }
539 };
540 
541 /* Units of thermal expansion of a material */
542 const AG_Unit agThermalExpansionUnits[] = {
543 	{ "um/m.k", "um/m\xc2\xb7k", "Micrometers per meter kelvin",	1.0, NULL },
544 	{ "mm/m.k", "mm/m\xc2\xb7k", "Millimeters per meter kelvin",	1e3, NULL },
545 	{ "m/m.k", "m/m\xc2\xb7k", "Meters per meter kelvin",		1e6, NULL },
546 	{ NULL, NULL, NULL,						0, NULL }
547 };
548 
549 /* Units of density of a material */
550 const AG_Unit agDensityUnits[] = {
551 	{ "mg/cm^3", "mg/cm\xc2\xb3", "Milligrams per cubic centimeter",	1e-3, NULL },
552 	{ "g/cm^3", "g/cm\xc2\xb3", "Grams per cubic centimeter",		1.0, NULL },
553 	{ "kg/cm^3", "kg/cm\xc2\xb3", "Kilograms per cubic centimeters",	1e3, NULL },
554 	{ NULL, NULL, NULL,							0, NULL }
555 };
556