It is not about converting values but about type checking at compile time.
For example, with this type checking, you cannot assign a duration to a distance, etc. Also the overhead is minimal.
This looks good, and is the kind of enforcement I was wanting.I am glad you like it and if it can be useful for you. :)
Looks nice. But maybe the overloading gets unwieldy. Perhaps a value in the record that gives the subtype of a dimension (any length, including units like angstrom etc)Yes, the overloading could get out of hand. In this example, I presume that only two units will be used but that's clearly not always the case.
It would save many, many overload routines even for just all the length units out there.
This is an interesting topic with a lot of promise for type safe general calculations involving dimensioned values. Consider that there are 7 base quantities (https://en.wikipedia.org/wiki/SI_base_unit) from which all other quantities (or physical units of measure) can be derived. If the current concept can be extended to handle arbitrary units of measure in a type safe way it would be mind blowing.I agree. It really is extremely interesting because it has the potential to be extremely useful.
A complicated mix of units which is difficult to keep track of manually, but if the compiler can ensure that the LHS and RHS base units simplify to the same (i.e. kg.m/s/s) then the expression is dimensionally consistent. Also, converting to any derived units become relatively simple, perhaps by having a table that map between the base units and any desired derived units.Basically, the compiler would need to have some counters that can be added and subtracted, that can be attached to a type. For example, s, s2 and 3 would be derived from the same generic type with a const parameter 1, 2 and 3.
The distance is: 20.2 km
The number of hundreds of meters is: 202
The time is: 2 h
Also: 120 min
The speed is: 10.1 km/h
Also: 2.80555555555556 m/s
Distance to go: 50 kilometers
Time to get there: 4.95049554455446 h
Also: 17822 s
The time to accelerate is: 10 s
The acceleration is: 0.280555555555556 m/s2
Also: 1.01 km/h/s
Gravity is: 9.81 meters per second squared
s2 = s*s? TRUE
m/s2*s = m/s? TRUE
The surface of a 10 m by 10 m square is: 100 m2
It is the same surface as a rectangle of 5 m by 20 m
From 3 kg, I can make 30 scoops of 100 g
Nice work. Potentially very useful. When polished I would like to see it as FPC package available out of the box.
program unitsOfMeasurement; uses Dimensioned, Math; var distance: TKilometers; time: THours; time2: TDuration; // SI unit is [s] speed: TKilometersPerHour; acceleration, gravity: TAcceleration; // SI unit is [m/s2] km_h_s: TAcceleration; side, side2: TLength; surface: TArea; mass: TKilograms; scoop: TMass; ...
3.0000000000000006E+002 =? 3.0000000000000000E+002
speed := 10*(m/s);
I agree that "UUnit" is not very beautiful. I will use "Dimensioned" instead.
1 m = 1000 mmRight on the spot! :D
I agree that "UUnit" is not very beautiful. I will use "Dimensioned" instead.I am not English native, but dim or dimensions still sound better to me over dimensioned. I guess si or metrics could be even better names, but since imperial units would probably end up there too - it might not be that great idea. Anyway, it's not that important and your contribution will be most welcome under any name. I already see it useful when publishing measurements with appropriate unit names under some MQTT or OPC server.
As I continue to experiment, it becomes clear that to reduce the number of operator definitions, I would need either:
- generic operators: similar to generic functions, but with operator, that could be applied to the various types that match the specializations.
- inheritance of class operators that refer to "self" type
I agree that "UUnit" is not very beautiful. I will use "Dimensioned" instead.How about "uom" (for "units of measure") ? short and unlikely to be confused with something else and, it does not presume being metric or imperial.
You could also take a look at syshelp.inc and how it uses single syshelpo.inc with different macro parameters to avoid code repetition and typing errors:Interesting. Indeed using $define could solve my repetition problems. :)
How about "uom" (for "units of measure") ? short and unlikely to be confused with something else and, it does not presume being metric or imperial.I don't know, it is original but not easy to remember, it sounds a bit mysterious unless you remember the acronym.
You're right, it has its pros and cons.How about "uom" (for "units of measure") ? short and unlikely to be confused with something else and, it does not presume being metric or imperial.I don't know, it is original but not easy to remember, it sounds a bit mysterious unless you remember the acronym.
I created a GitHub repository called DimPas.Sorry, GPL3 is a show stopper for me since I create closed source a lot. That fact also switched my point of view so now I would like to see it as a package in FPC only if license changes to something more liberal - at least FPC modified LGPL.
https://github.com/circular17/DimPas
I created a GitHub repository called DimPas.Sorry, GPL3 is a show stopper for me since I create closed source a lot. That fact also switched my point of view so now I would like to see it as a package in FPC only if license changes to something more liberal - at least FPC modified LGPL.
https://github.com/circular17/DimPas
I modified the licenses to LGPL3+link exception.Thanks! :D
If you distribute this library in an executable, you must make the source available for 3 years.
I've put a LICENSE.modifiedLGPL file.Thanks again! :D 8-) :D
About operator overloading, inside a class, it can be defined only if TSelf appears in the parameters * and /. The compiler does not complain but it will be ignored otherwise. That's why if we want m3/m2 then it needs to be defined outside of the meter records.
We can avoid this problem by calling things: square, cubic, quartic, quintic etc. Also the names can be made more consistent, sometimes I've put the cubed sometimes before sometimes after. So I will fix that.
kg/s2 is an acceleration, how fast I will get fat :D:D
I think is more common to multiply N/m (stifness) for m for having N (force).TNewton is a TFactoredUnit because it is uses kg instead of g. So I suppose you can combine it with TMeter with TFactoredNumeratorUnit.
Now, TNewton isn't a TUnit and we can't define N/m as TUnitRatio. How to fix it ?
TNewton is a TFactoredUnit because it is uses kg instead of g. So I suppose you can combine it with TMeter with TFactoredNumeratorUnit.... but TFactoredNumeratorUnitIdentifier and TFactoredNumeratorUnitQuantity need TUnit not TFactoredUnit.
If that's too complicated we might want to define two kilograms unit. One being the factored unit from the gram, and one begin the SI base unit.
... but TFactoredNumeratorUnitIdentifier and TFactoredNumeratorUnitQuantity need TUnit not TFactoredUnit.That's because unfactored versions of the units come first as generic parameters. But anyway let's simplify.
and then can a user combine units derived from these the two kg units ?Yes. Basically the "kg" identifier will still be the one derived from the gram, allowing to do conversions to g, mg... But when combined, it will become the new TBaseKilogram unit.
:'(
... the "kg" identifier will still be the one derived from the gram...Huh, shouldn't it be the other way around (g derived from kg)? kg (not g) is base SI unit:
What I see missing are micro and nano (um, nm, us, ns)
marcov, Bogen85, Warfley, ccrause, 440bx, avra, VisualLab you seemed interested by such package. I would say most of the obstacles have been dealt with.I'm not, at the moment, working on a physics problem, because of this I currently don't need to deal with units but, it's quite likely that I will sometime in the future. At that time, I will take your unit out for a "walk" ;)
Do you have an actual use of the package, suggestions or contributions to propose?
dim.pas(154,20) Error: Function is already declared Public/Forward "operator /(const TDimensionedQuantityProduct$2;const TDimensionedQuantityProduct$2.TDimensionedQuantity$1$crc92C318DE):<record type>; Static;But the type of the parameter is not the same (TQuantity1 and TQuantity2).
Each specialization of a generic class with the same types as parameters is a new, distinct type, but these types are assignment compatible if the template types used to specialize them are equal.