www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - RFC: Units of measurement for D (Phobos?)

reply David Nadlinger <see klickverbot.at> writes:
Recently, I have been playing around with a little units of measurement 
system in D. As this topic has already been brought up quite a number of 
times here, I thought I would put my implementation up for discussion here.

When this topic came up previously, it has been proposed to include 
units support with Phobos, and thus I have merged my work into my Phobos 
fork. Please note, however, that even if we should come to the 
conclusion that we really want something like this in Phobos, this is 
not a formal review request yet. There are still a couple of items left 
on my to-do list, but I'd like to get some feedback first.

Anyway, here is a link to the code: 
https://github.com/klickverbot/phobos/tree/units (std/units.d and 
std/si.d). Also, I put up a build of the DDoc output at 
http://klickverbot.at/code/units/std_units.html resp. 
http://klickverbot.at/code/units/std_si.html.


A couple of notes:

  - DDoc emits the documentation for some template functions twice,
once for the template, and once for the eponymous function itself (bug 
4107). Is there a workaround for this issue? This also affects, amongst 
others, the docs for std.container.

  - The documentation could use quite a bit of work in general, I'd be 
happy about any suggestions.

  - In a previous discussion, Andrei brought up the topic of categorical 
types implemented as quantities without any operators defined. An extra 
template parameter to disable arithmetic could easily be added to 
Quantity, if deemed useful. However, I think that using an units system 
to define them is pretty much overkill, as neither conversions nor 
arithmetic operations would be used.

  - Currently, »auto« returns are used quite liberally for things that 
should »just work«, e.g. just mirror underlying value type operations. 
This has the advantage of keeping code and function signatures readable, 
but obviously also hides the real type from the user. Any other thoughts 
on this?

  - I have followed the general Phobos guidelines to use template 
constraints where they would logically belong (and where they are 
actually implementable without hacks due to DMD bugs), instead of, say, 
static asserts or just letting instantiation fail. However, this way, 
you lose the ability to specify helpful error messages (which is 
somewhat important as the underlying types can be quite complex), and 
the DDoc documentation is cluttered up somewhat.

  - The helper functions for creating instances of new unit types 
(scale, affine, ...) are currently template functions taking an instance 
of the unit they manipulate as actual argument. This is only for 
»historical« reasons really, would it be cleaner to use just templates?

  - If this library should really be included into Phobos eventually, I 
am not quite sure about the right organization of the code. While I 
think that std.units would be a good fit for the core module, I am not 
sure how modules containing definitions of actual physical units and 
other related code (e.g. CODATA values for the natural constants) should 
be organized. Putting them directly into std.* is certainly a bad idea, 
as it would add even more clutter to the already crowded (overcrowded, 
in my opinion) package. What about a new std.physical (or similar) package?


David
Apr 12 2011
next sibling parent "Nick Sabalausky" <a a.a> writes:
I see no one's responded yet. FWIW, I love the idea of having a static units 
system in D. But I just haven't really had a chance to look through your 
post here, or your code. So busy...  :(
Apr 14 2011
prev sibling next sibling parent reply Simen Kjaeraas <simen.kjaras gmail.com> writes:
This looks very good. I'd suggest calling them std.units and std.units.si, if
possible.
It seems to support all the features I wanted when I started writing such a
module, though I never finished mine.
The documentation is very nice if, as you said, somewhat duplicated. Could
perhaps use a better first example, maybe also suggestions for its use (I'd
like to see OpenGL headers using this for vectors, angles, etc).

All in all, it seems a high-quality submission, and I'm prepared to vote for
its inclusion in Phobos.

--
  Simen
Apr 15 2011
next sibling parent reply Simen Kjaeraas <simen.kjaras gmail.com> writes:
Oh, and it would appear I have found a bug:

enum foo = metre / 2;
std\units.d(165): Error: cannot raise int to a negative integer power. Did you m
ean (cast(real)rhs)^^-1 ?
Apr 15 2011
parent David Nadlinger <see klickverbot.at> writes:
On 4/15/11 3:06 PM, Simen Kjaeraas wrote:
 Oh, and it would appear I have found a bug:

 enum foo = metre / 2;
 std\units.d(165): Error: cannot raise int to a negative integer power. Did you
m
 ean (cast(real)rhs)^^-1 ?
Oh, thanks, I just pushed a fix (which uses (rhs ^^ 0) / rhs to work around the issue for integer types). Be aware, however, that your code might not be what you want – the value type is inferred to int, and thus the result is 0 * metre… David
Apr 15 2011
prev sibling parent David Nadlinger <see klickverbot.at> writes:
On 4/15/11 2:24 PM, Simen Kjaeraas wrote:
 This looks very good. I'd suggest calling them std.units and std.units.si, if
possible.
Thanks for your comments. Unfortunately, having a package of the same name as a module is not possible in D – any other ideas? What about std.measure(ment).*? David
Apr 15 2011
prev sibling next sibling parent David Nadlinger <see klickverbot.at> writes:
On 4/12/11 6:40 PM, David Nadlinger wrote:
 - The helper functions for creating instances of new unit types (scale,
 affine, ...) are currently template functions taking an instance of the
 unit they manipulate as actual argument. This is only for »historical«
 reasons really, would it be cleaner to use just templates?
I just went ahead and changed them to pure templates, having the unit helpers as functions only to infer the type of the passed unit instance really made no sense in the current design (which uses template alias parameters to pass unit instances heavily anyway). Another missing thing I didn't mention in the original post is support for named derived units – currently, there is no way you could enable (kilogram * metre / pow!2(second) to be printed as »Newton«. It wouldn't be hard to implement, but I didn't really feel the need for it so far… David
Apr 16 2011
prev sibling next sibling parent =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
Is somebody waiting for this to be reviewed?

/Per
Feb 26 2014
prev sibling next sibling parent reply "Kelet" <kelethunter gmail.com> writes:
Tangentially related: https://github.com/biozic/quantities
Feb 26 2014
parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
On Wednesday, 26 February 2014 at 21:41:57 UTC, Kelet wrote:
 Tangentially related: https://github.com/biozic/quantities
Impressive! This seems similar to David Nadlingers std.units and std.si. When will all these efforts on implementing Units/SI be synchronized and reviewed? One question: I know what angles are but I have never seen them defined like this before! enum radian = meter / meter; // ditto enum steradian = square(meter) / square(meter); /// ditto What on earth does this mean? /Per
Feb 26 2014
next sibling parent "Michael" <pongad gmail.com> writes:
 enum radian = meter / meter; // ditto
 enum steradian = square(meter) / square(meter); /// ditto

 What on earth does this mean?
It has to do with the definition of radian itself. If you draw a circle (of any radius) around an angle. The measure of the angle is radian is the ratio between the arc length of the circle and the radius. This is the reason why one full rotation is 2*pi radians: A circle's circumference is always 2*pi times its radius. Steradian is similar, but in three dimensions.
Feb 26 2014
prev sibling parent reply "Nicolas Sicard" <dransic gmail.com> writes:
On Wednesday, 26 February 2014 at 22:49:57 UTC, Nordlöw wrote:
 On Wednesday, 26 February 2014 at 21:41:57 UTC, Kelet wrote:
 Tangentially related: https://github.com/biozic/quantities
Impressive! This seems similar to David Nadlingers std.units and std.si. When will all these efforts on implementing Units/SI be synchronized and reviewed? One question: I know what angles are but I have never seen them defined like this before! enum radian = meter / meter; // ditto enum steradian = square(meter) / square(meter); /// ditto What on earth does this mean? /Per
Thanks! I think David Nadlingers' is more elaborate (scaled and affine units) and less prone to rounding errors. I haven't used it yet. Mine is more basic but has a parsing system that I use to define units quickly at compile-time and parse data files at runtime. -- Nicolas
Mar 04 2014
parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
 Thanks! I think David Nadlingers' is more elaborate (scaled and
 affine units) and less prone to rounding errors. I haven't used
 it yet. Mine is more basic but has a parsing system that I use 
 to
So you cannot defined things lika kPa from Pa in compile-time?
 define units quickly at compile-time
Can't David's package also quickly define in compile-time? Have you thought about merging your effort vid Davids and propose it to Phobos? This issue has stale for quite some time know. I would like to have support add support for geometric units like angles, coordinate systems, etc. Have you thought about integrating these with your module?
Mar 04 2014
parent "Nicolas Sicard" <dransic gmail.com> writes:
On Tuesday, 4 March 2014 at 13:20:02 UTC, Nordlöw wrote:
 Thanks! I think David Nadlingers' is more elaborate (scaled and
 affine units) and less prone to rounding errors. I haven't used
 it yet. Mine is more basic but has a parsing system that I use 
 to
So you cannot defined things lika kPa from Pa in compile-time?
enum kPa = kilo(pascal); which is equivalent to enum kPa = 1000 * pascal; Note that my module defines no real unit type, just quantities: a unit is only a special quantity with a value of 1 and a set of dimensions (a "base unit" in the sense of the SI). I think it better fits what physical units really are. kPa would then be a quantity that stores 1000 and a set of dimensions corresponding to a pressure. If you declare: auto p = 101.3 * kPa; p stores a value that is 101.3 * 1000 internally, not 101.3. With David's library, I think you can declare kilopascal as a scaled unit derived from pascal, and then a quantity in kilopascal would actually store 101.3. The result is globally the same, but in fact the representations of the numeric values would be a bit different, and so would the rounding errors, when using floating point types.
 define units quickly at compile-time
Can't David's package also quickly define in compile-time?
I think it can.
 Have you thought about merging your effort vid Davids and 
 propose it to Phobos? This issue has stale for quite some time 
 know.
I just think that David's package could have been proposed for Phobos a long time ago. I don't know what has stopped it then. I developed mine afterwards, not being aware of David's one.
 I would like to have support add support for geometric units 
 like angles, coordinate systems, etc. Have you thought about 
 integrating these with your module?
My package is extendable. The SI module is just a predefined set of common quantities and prefixes. You can use your own. Some angle units are defined in quantites.si. I am not sure of what you call a coordinate systems in this respect. -- Nicolas
Mar 04 2014
prev sibling next sibling parent reply "Per =?UTF-8?B?Tm9yZGzDtnci?= <per.nordlow gmail.com> writes:
On Tuesday, 12 April 2011 at 16:44:10 UTC, David Nadlinger wrote:
 Recently, I have been playing around with a little units of 
 measurement system in D. As this topic has already been brought 
 up quite a number of times here, I thought I would put my 
 implementation up for discussion here.
I would like to move forward with std.experimental.unit(s). A question that needs to be decided on Before starting this is: - David's library and quantities use different interal representation. Davids 7-dimensional vector of rational integers (a la Boost) is hardcoded to represent SI units. biozic's is not and uses a tuple of strings and is therefore more flexible. Which direction should we choose?
Sep 09 2015
next sibling parent "Robert burner Schadek" <rburners gmail.com> writes:
On Wednesday, 9 September 2015 at 07:04:05 UTC, Per Nordlöw wrote:
 Which direction should we choose?
quantities
Sep 09 2015
prev sibling parent reply "David Nadlinger" <code klickverbot.at> writes:
On Wednesday, 9 September 2015 at 07:04:05 UTC, Per Nordlöw wrote:
 - David's library and quantities use different interal 
 representation. Davids 7-dimensional vector of rational 
 integers (a la Boost) is hardcoded to represent SI units.
You must be confusing the library with something else (or me with another David). I'm pretty sure that my original proof-of-concept is the most flexible of all of them, coming with support for composing arbitrary runtime conversion functions, affine quantities and so on. SI unit definitions are merely predefined in a second module because they are commonly used. That being said, my implementation is ages old and could probably be done much better today. - David
Sep 10 2015
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Thursday, 10 September 2015 at 07:01:19 UTC, David Nadlinger 
wrote:
 You must be confusing the library with something else (or me 
 with another David). I'm pretty sure that my original 
 proof-of-concept is the most flexible of all of them, coming 
 with support for composing arbitrary runtime conversion 
 functions, affine quantities and so on. SI unit definitions are 
 merely predefined in a second module because they are commonly 
 used.

 That being said, my implementation is ages old and could 
 probably be done much better today.

  - David
I've gained time and energy to take up this task again. It seems like David Nadlinger's solution is very complete: https://github.com/klickverbot/phobos/tree/undefined http://klickverbot.at/code/units/std_units.html http://klickverbot.at/code/units/std_units.html#PrefixSystem but not a complete superset of https://github.com/nordlow/quantities/tree/master/source/undefined One key issue here is whether we should provide an instantiator based API auto q = 1.0.meter; or operator plus constants/CT-constants (via David's std.si) import std.si : meter; const q = 1.0*meter; or a combined (my proposal) auto q = 1.0.meters; // plural naming auto q = 1.0*meter; // singular naming for expressing quantities. David's SI-unit solution is, IMO, better than biozic's as it doesn't force the unit to be associated with a specific numerical scalar type upon construction. Another key-question is whether we should support biozic's compile-time parsing of unit expressions such as - 1.0.si!"km/h" - 1.0.si!"m/s" etc. Could somebody point out if something is missing in David's solution. And, if so, which parts of biozic's which could be reused. that could/should be reused for filling in these gaps. Another key-issue is if the template `Rational` in std.units should be extracted and put into a separate module. I vote for moving forward with David's solution.
Mar 14
next sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Monday, 14 March 2016 at 09:04:28 UTC, Nordlöw wrote:
 http://klickverbot.at/code/units/std_units.html#PrefixSystem
Should be: http://klickverbot.at/code/units/std_si.html
Mar 14
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Monday, 14 March 2016 at 09:10:21 UTC, Nordlöw wrote:
 http://klickverbot.at/code/units/std_si.html
One more thing: Angular units: I suggest non-SI-derived units for `Radian` and `Steradian` instead. Then, degrees and other derived angular units shall be expressed as scaled versions of these. I don't see the point in defining these as meter/meter and meter^^2/meter^^2 in the type system. Destroy!
Mar 14
parent =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Monday, 14 March 2016 at 09:37:10 UTC, Nordlöw wrote:
 One more thing: Angular units: I suggest non-SI-derived units 
 for `Radian` and `Steradian` instead. Then, degrees and other 
 derived angular units shall be expressed as scaled versions of 
 these.
Oops, already defined here: http://klickverbot.at/code/units/std_si.html#radian Thanks, David.
Mar 14
prev sibling next sibling parent reply Chris Wright <dhasenan gmail.com> writes:
On Mon, 14 Mar 2016 09:04:28 +0000, Nordlöw wrote:
 I've gained time and energy to take up this task again. It seems like
 David Nadlinger's solution is very complete:
 
 https://github.com/klickverbot/phobos/tree/undefined
 
 http://klickverbot.at/code/units/std_si.html
Ohm my, that's awesome. Watt needs to happen to get this into Phobos?
Mar 14
next sibling parent reply Robert burner Schadek <rburners gmail.com> writes:
have a look at this!

https://github.com/biozic/quantities
Mar 14
next sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Monday, 14 March 2016 at 19:08:18 UTC, Robert burner Schadek 
wrote:
 have a look at this!

 https://github.com/biozic/quantities
Could you briefly outline why you prefer this over David's work?
Mar 15
parent Robert burner Schadek <rburners gmail.com> writes:
On Tuesday, 15 March 2016 at 09:08:11 UTC, Nordlöw wrote:
 On Monday, 14 March 2016 at 19:08:18 UTC, Robert burner Schadek 
 wrote:
 have a look at this!

 https://github.com/biozic/quantities
Could you briefly outline why you prefer this over David's work?
- has been in code.dlang.org since 2014 - maintained - good CT string parsing abilities - ... have a look at the github page! its inclusion has been discussed before (did go nowhere because author was busy, issue is still assigned to his github project)
Mar 15
prev sibling parent David Nadlinger <code klickverbot.at> writes:
On Monday, 14 March 2016 at 19:08:18 UTC, Robert burner Schadek 
wrote:
 have a look at this!

 https://github.com/biozic/quantities
This has been brought up (and subsequently discussed) on the first page of this thread, more than two years ago. — David
Mar 15
prev sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Monday, 14 March 2016 at 18:51:45 UTC, Chris Wright wrote:
 Ohm my, that's awesome. Watt needs to happen to get this into 
 Phobos?
I'm cleaning up David's work right and will put up a PR today.
Mar 15
parent reply David Nadlinger <code klickverbot.at> writes:
On Tuesday, 15 March 2016 at 09:07:05 UTC, Nordlöw wrote:
 On Monday, 14 March 2016 at 18:51:45 UTC, Chris Wright wrote:
 Ohm my, that's awesome. Watt needs to happen to get this into 
 Phobos?
I'm cleaning up David's work right and will put up a PR today.
Please make a really, really thorough pass through the source before proposing it for Phobos. The code was written in a dark age where CTFE bugs were very common (e.g. trying to use std.algorithm.sort would give weird results), there was a number of issues with template parameters, and many relevant features simply did not exist yet: - UFCS (!) - UDAs - Extracting template symbol/arguments from template instances - Natural alias syntax ("=") - alias/enum/… templates - Eponymous templates with extra members - … Back then, getting this to work with a half-reasonable API in spite of all the compiler bugs and limitations was quite the tour de force (IIRC some of the issues are marked using BUG in the code, but that was by far not all of them). With the current compilers, it should be much more a question of design than of implementation. The basic design should still be sound, though. The main decisions to make concern not so much the implementation (or whether unit string parsing is implemented, etc.) but the level of flexibility in the unit and conversion structure. One such decision would be whether to store a) the numerical value verbatim in the units specified by the user, or b) in some distinguished base unit for the given dimension. Another such question is whether to use 1) a pre-defined, closed system of dimensions (e.g. the SI units), 2) an explicit, but extensible structure of dimensions (to which units can be assigned), or 3) units can arbitrarily be created and the concept of dimensions emerges implicitly from conversions between them. The less flexible solutions often have the advantage of allowing a simpler implementation, being easier to understand for the novice user (less types/templates) and possibly being quicker to compile. For my original library, the general motif was the to follow the most expressive and flexible solution (3) and a) in the above). For instance, on top of the obvious consequences regarding precision, going with a) allows you to seamlessly interface with non-unit-aware code and to define runtime conversions that are only applied when actually requested by the user. Similar considerations apply to other aspects of the design. — David
Mar 15
next sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 16 March 2016 at 02:03:09 UTC, David Nadlinger 
wrote:
 Please make a really, really thorough pass through the source 
 before proposing it for Phobos.
Thanks! I'm working on these issues right now.
Mar 16
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 16 March 2016 at 11:28:05 UTC, Nordlöw wrote:
 I'm working on these issues right now.
Regularly updated here: https://github.com/nordlow/justd/blob/master/units.d https://github.com/nordlow/justd/blob/master/si.d
Mar 16
parent reply ZombineDev <petar.p.kirov gmail.com> writes:
On Wednesday, 16 March 2016 at 13:39:48 UTC, Nordlöw wrote:
 On Wednesday, 16 March 2016 at 11:28:05 UTC, Nordlöw wrote:
 I'm working on these issues right now.
Regularly updated here: https://github.com/nordlow/justd/blob/master/units.d https://github.com/nordlow/justd/blob/master/si.d
BTW, is there overlap between a unit system library and Andrei's BigO system? Maybe it would be useful if the later can be expressed with the former.
Mar 16
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 16 March 2016 at 13:57:51 UTC, ZombineDev wrote:
 BTW, is there overlap between a unit system library and 
 Andrei's BigO system? Maybe it would be useful if the later can 
 be expressed with the former.
Interesting. Could you elaborate? What units should be involved? Andralex?
Mar 16
next sibling parent reply ZombineDev <petar.p.kirov gmail.com> writes:
On Wednesday, 16 March 2016 at 14:19:56 UTC, Nordlöw wrote:
 On Wednesday, 16 March 2016 at 13:57:51 UTC, ZombineDev wrote:
 BTW, is there overlap between a unit system library and 
 Andrei's BigO system? Maybe it would be useful if the later 
 can be expressed with the former.
Interesting. Could you elaborate? What units should be involved? Andralex?
I think it started here: http://forum.dlang.org/post/n3sdm1$1fba$1 digitalmars.com See also: http://forum.dlang.org/post/n3t8f8$2ii6$1 digitalmars.com http://forum.dlang.org/post/n4s66a$i9u$1 digitalmars.com https://issues.dlang.org/show_bug.cgi?id=15464 The two dimensions are time and space (memory). They are not expressed in absolute units of measurement, but show approximate rate of growth as the size of the input grows. Andrei's proposal defines an algebra over them. A system of units is also an algebra, so I wondering if we can somehow generalize the essence of both ideas. BTW, after rereading the links above, I came up with a related idea: When you have a large existing codebase it may be too much work to change all types to be strongly typed like this: ============================== // before: struct Car { double relativeSpeed(Car other); // measured in km/h double relativeDistance(Car other); // measured in km } // after: alias KMpH = kilo!Metre / Second(3600); struct Car { KMpH!double relativeSpeed(Car other); kilo!(Metre!(double)) relativeDistance(Car other); } ============================== Sometimes a more gradual approach may be useful: ============================== // before: struct Car { double relativeSpeed(Car other); // km/h double relativeDistance(Car other); // km } // after: alias KMpH = kilo!Metre / Second(3600); struct Car { double relativeSpeed(Car other) Unit!KMpH; double relativeDistance(Car other) Unit!(kilo!Metre); } ==============================
Mar 16
parent David Nadlinger <code klickverbot.at> writes:
On Wednesday, 16 March 2016 at 17:12:42 UTC, ZombineDev wrote:
 Sometimes a more gradual approach may be useful:

 […]
How would this be any more than an informational annotation? If anything, you could build a custom lint tool to propagate and verify the unit annotations, but I don't quite see how the type system/compiler would make use of it. — David
Mar 16
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/16/16 7:19 AM, Nordlöw wrote:
 On Wednesday, 16 March 2016 at 13:57:51 UTC, ZombineDev wrote:
 BTW, is there overlap between a unit system library and Andrei's BigO
 system? Maybe it would be useful if the later can be expressed with
 the former.
Interesting. Could you elaborate? What units should be involved? Andralex?
I don't see overlap, but I may be wrong. -- Andrei
Mar 16
prev sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 16 March 2016 at 02:03:09 UTC, David Nadlinger 
wrote:
 The code was written in a dark age where CTFE bugs were very 
 common (e.g. trying to use std.algorithm.sort would give weird 
 results), there was a number of issues with template 
 parameters, and many relevant features simply did not exist yet:
  - UFCS (!)
Done
  - UDAs
Could you elaborate on possible usage in this case?
  - Extracting template symbol/arguments from template instances
Could you elaborate on possible usage in this case?
  - Natural alias syntax ("=")
Done
  - alias/enum/… templates
Done
  - Eponymous templates with extra members
Could you elaborate on possible usage in this case?
Mar 16
parent reply David Nadlinger <code klickverbot.at> writes:
Hi Per,

Many thanks for working on the code! Could you put it up as a 
separate Dub package to make it easier for people to try out? 
`justd` is an 68 MiB-heavy clone, which makes it somewhat 
cumbersome to play around with and contribute to it. You'd 
probably also want to add your name to the Authors list.

On Wednesday, 16 March 2016 at 14:27:16 UTC, Nordlöw wrote:
  - UFCS (!)
Done
There might be additional design possibilities now that didn't previously exist. The way of constructing a quantity is one such example, although I still like the approach using `*`.
  - UDAs
Could you elaborate on possible usage in this case?
For example, to replace SuperSecretAliasToMarkThisAsUnit. It could conceivably also be used for the extra metadata like the base linear unit for affine units, etc.
  - Extracting template symbol/arguments from template instances
Could you elaborate on possible usage in this case?
IIRC there are various `isXyz` templates where I went with a duck typing approach out of necessity (which might or might not be a better design choice than just checking for a certain template instance).
  - Eponymous templates with extra members
Could you elaborate on possible usage in this case?
The code in and around GetConversion can probably be simplified. It currently explicitly uses `.Result` members and so on. Another thing I forgot to mention in the previous post are documented unit tests. Pretty much all of the example blocks should probably be converted to it. The CTFE-related code could also use a closer look, for example makeIndexCtfe() is probably not needed any longer. Best, David
Mar 16
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 16 March 2016 at 17:46:39 UTC, David Nadlinger 
wrote:
 Hi Per,

 Many thanks for working on the code! Could you put it up as a 
 separate Dub package to make it easier for people to try out?
Ok, I'll do that in a couple of days. In the mean while could you take a look at the overloads of sin, cos and tan in si.d. I just want to start at something, IMHO, having type-safe handling of angles in trigonometric functions would some projects more correct. This is cheap solution (used by many unit-libraries) uses a floating-point-scaling of the radian unit. Which of course may result in loss accuracy. A better approach to represent degrees would of course be to use `ScaledUnit`. How should then sin, cos, tan, expi be redesigned to support `ScaledUnit` aswell as `Quantity`? Could you, please, highlight the basic idea here or perhaps give a code. Thanks in advance, David.
Mar 16
parent reply David Nadlinger <code klickverbot.at> writes:
On Wednesday, 16 March 2016 at 22:16:20 UTC, Nordlöw wrote:
 How should then sin, cos, tan, expi be redesigned to support 
 `ScaledUnit` aswell as `Quantity`?
What you can do is to take an arbitrary quantity with an (angle.canConvert!radian) template constraint. Inside the function, you then simply use cos(angle.convert!radian / radian) or whatever. — David
Mar 16
parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Wednesday, 16 March 2016 at 22:34:04 UTC, David Nadlinger 
wrote:
 What you can do is to take an arbitrary quantity with an 
 (angle.canConvert!radian) template constraint. Inside the
I believe `isConvertableTo` is a more Phobos-compliant naming, right? Is there are reason why `convert` wasn't named the shorter and Phobos-compliant `to` instead? Was this prior to `std.conv.to`?
 function, you then simply use cos(angle.convert!radian / 
 radian) or whatever.
Why not simply add a Quantity member auto ref toValue() const used as cos(angle.to!radian.toValue) Shorter and puts less stress on the compiler.
Mar 17
next sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Thursday, 17 March 2016 at 12:51:28 UTC, Nordlöw wrote:
 I believe `isConvertableTo` is a more Phobos-compliant naming, 
 right?
Correction: Should be named `isConvertibleTo`. BTW: We already have https://dlang.org/phobos/std_traits.html#isImplicitlyConvertible Why don't we already have isConvertibleTo or/and isExplicitlyConvertibleTo
Mar 17
parent =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Thursday, 17 March 2016 at 12:55:39

Ping, David Nadlinger! 😊
Mar 18
prev sibling parent David Nadlinger <code klickverbot.at> writes:
On Thursday, 17 March 2016 at 12:51:28 UTC, Nordlöw wrote:
 I believe `isConvertableTo` is a more Phobos-compliant naming, 
 right?
I went for canConvert since it is a bit shorter than isConvertible and there is precedent for it in Phobos as well (e.g. find/canFind). It's a matter of taste, though. If I were to work on the library again today, I might just as well go for isConvertible.
 Is there are reason why `convert` wasn't named the shorter and 
 Phobos-compliant `to` instead?
One thing to consider is that convert!U differs from to!T in that the latter returns something of type T, whereas the former returns a Quantity!(U, …). This seems enough of a difference that choosing the same name as the widely used std.conv.to might be somewhat misleading (even though I usually advocate for using the module system for disambiguating names).
 function, you then simply use cos(angle.convert!radian / 
 radian) or whatever.
Why not simply add a Quantity member […] toValue()
This is again a design decision that can go either way. The choice I made was deliberate, although of course not above debate: Since I chose to have dimensionless quantities implicitly convert to "plain" value types, it seemed superfluous to add another primitive (`a / a.unit` is simple enough to write). Furthermore, it underlines the point that `*` and `/` between quantities and units do not actually change the numeric value, but merely modify its units. Making use of that for the "core functionality" seemed like a cute way to drive the point home to users. Explicitly specifying the unit also helps avoiding mistakes in generic code. If you want to go the other route, I would suggest carefully deliberating the naming scheme, since discarding unit information is a lossy and potentially "unsafe" (as in code correctness). In an attempt to make this obvious in the current implementation (where it is only enabled for dimensionless quantities), I named the function rawValue(). For example, renaming (fromValue, rawValue) to {from, to}Raw() might be clearer than {from, to}Value(). By the way, I highly doubt that "puts less stress on the compiler" is a valid argument for that decision. In that regard, the big elephant in the room is GetConversion, which you might want to re-do using a breadth-first search anyway (see TODO comments; I couldn't be bothered to implement it back then due to the numerous DMD bugs I had to fight). — David
Mar 18
prev sibling next sibling parent reply =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Monday, 14 March 2016 at 09:04:28 UTC, Nordlöw wrote:
 http://klickverbot.at/code/units/std_units.html
 http://klickverbot.at/code/units/std_units.html#PrefixSystem
No module name in Phobos is currently in plural form. I suggest we stick to that standard a name these std.experimental.unit std.experimental.unit.si One thing. How should these modules be represented on the file system? Destroy!
Mar 15
next sibling parent reply Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Tuesday, 15 March 2016 at 09:13:10 UTC, Nordlöw wrote:
 On Monday, 14 March 2016 at 09:04:28 UTC, Nordlöw wrote:
 http://klickverbot.at/code/units/std_units.html
 http://klickverbot.at/code/units/std_units.html#PrefixSystem
No module name in Phobos is currently in plural form.
std.traits std.signals std.typecons ;-)
 I suggest we stick to that standard a name these

 std.experimental.unit
 std.experimental.unit.si

 One thing. How should these modules be represented on the file 
 system?
std/experimental/unit/package.d std/experimental/unit/si.d For some other modules, Andrei has insisted that package.d must publicly import all subpackages, but I see no reason for this. std.experimental.unit can contain the basic general functionality, and std.experimental.unit.si the SI specific ones.
Mar 15
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 3/15/16 3:31 AM, Marc Schütz wrote:
 For some other modules, Andrei has insisted that package.d must publicly
 import all subpackages
Not too strongly, I think std.allocator doesn't do that. But the judgment must be thoroughly sound and explained. For the putative package, importing packagename should generally be the same as import packagename.everything. -- Andrei
Mar 15
prev sibling parent reply D.Enguiyen <d.eng nowhere.gr> writes:
On Tuesday, 15 March 2016 at 09:13:10 UTC, Nordlöw wrote:
 On Monday, 14 March 2016 at 09:04:28 UTC, Nordlöw wrote:
 http://klickverbot.at/code/units/std_units.html
 http://klickverbot.at/code/units/std_units.html#PrefixSystem
No module name in Phobos is currently in plural form. I suggest we stick to that standard a name these std.experimental.unit std.experimental.unit.si One thing. How should these modules be represented on the file system? Destroy!
Is it able to manage quantities with a non-linear transformations, for example when dealing with octet and byte ? (1024)!"byte" == 1!"kbyte";
Mar 15
next sibling parent reply D.Enguiyen <d.eng nowhere.gr> writes:
On Tuesday, 15 March 2016 at 14:46:30 UTC, D.Enguiyen wrote:
 Is it able to manage quantities with a non-linear 
 transformations, for example when dealing with octet and byte ?

 (1024)!"byte" == 1!"kbyte";
1!"byte" * 1024 == 1!"kbyte";
Mar 15
parent D.Enguiyen <d.eng nowhere.gr> writes:
On Tuesday, 15 March 2016 at 14:50:42 UTC, D.Enguiyen wrote:
 On Tuesday, 15 March 2016 at 14:46:30 UTC, D.Enguiyen wrote:
 Is it able to manage quantities with a non-linear 
 transformations, for example when dealing with octet and byte ?

 (1024)!"byte" == 1!"kbyte";
1!"byte" * 1024 == 1!"kbyte";
I meant byte!1 * 1024 == kbyte!1;
Mar 15
prev sibling parent David Nadlinger <code klickverbot.at> writes:
On Tuesday, 15 March 2016 at 14:46:30 UTC, D.Enguiyen wrote:
 Is it able to manage quantities with a non-linear 
 transformations, for example when dealing with octet and byte ?

 (1024)!"byte" == 1!"kbyte";
There are no non-linear transformations going on here, following usual math terminology. If your question is whether unit conversions are possible with non-power-of-ten factors, the answer is an empathic "yes" – the scale factors could even be determined at run-time! The most basic solution would be to define a scaled unit like this: enum kibyte = scale!(byte, 1024, "kibibyte", "kiB"); You would probably want to define a power-of-two PrefixSystem though. (http://klickverbot.at/code/units/std_units.html#PrefixSystem) — David
Mar 15
prev sibling parent deed <none none.none> writes:
On Monday, 14 March 2016 at 09:04:28 UTC, Nordlöw wrote:

 Could somebody point out if something is missing in David's 
 solution. And, if so, which parts of biozic's which could be 
 reused.

 that could/should be reused for filling in these gaps.
Last time I evaluated these modules, I recall issues with exponents. I have to dig to find excact limitations, but IIRC you couldn't express rational exponents or evaluate expressions with them, like the square root of a meter or squaring the square root of a meter. Or was it only the operator "^^" that wasn't supported?
Mar 16
prev sibling next sibling parent reply "HaraldZealot" <harald_zealot tut.by> writes:
On Tuesday, 12 April 2011 at 16:44:10 UTC, David Nadlinger wrote:
 Recently, I have been playing around with a little units of 
 measurement system in D. As this topic has already been brought 
 up quite a number of times here, I thought I would put my 
 implementation up for discussion here.

 ...

 Anyway, here is a link to the code: 
 https://github.com/klickverbot/phobos/tree/units (std/units.d 
 and std/si.d). Also, I put up a build of the DDoc output at 
 http://klickverbot.at/code/units/std_units.html resp. 
 http://klickverbot.at/code/units/std_si.html.

 ...

 David
One big problem is, that in SI base unit for mass is kilogram not gram.
Sep 09 2015
parent "David Nadlinger" <code klickverbot.at> writes:
On Wednesday, 9 September 2015 at 15:21:22 UTC, HaraldZealot 
wrote:
 One big problem is, that in SI base unit for mass is kilogram 
 not gram.
This is definitely not a "big problem". There is nothing that sets apart the "base" units in my old library from any other units, except for the fact that they happen to be defined using baseUnit!(), not by adding a prefix. Kilogram just happens to be defined as kilo!gram so that you don't get things like millikilogram. — David
Sep 10 2015
prev sibling parent reply Zardoz <luis.panadero gmail.com> writes:
On Tuesday, 12 April 2011 at 16:44:10 UTC, David Nadlinger wrote:
 Recently, I have been playing around with a little units of 
 measurement system in D. As this topic has already been brought 
 up quite a number of times here, I thought I would put my 
 implementation up for discussion here.

 When this topic came up previously, it has been proposed to 
 include units support with Phobos, and thus I have merged my 
 work into my Phobos fork. Please note, however, that even if we 
 should come to the conclusion that we really want something 
 like this in Phobos, this is not a formal review request yet. 
 There are still a couple of items left on my to-do list, but 
 I'd like to get some feedback first.

 Anyway, here is a link to the code: 
 https://github.com/klickverbot/phobos/tree/units (std/units.d 
 and std/si.d). Also, I put up a build of the DDoc output at 
 http://klickverbot.at/code/units/std_units.html resp. 
 http://klickverbot.at/code/units/std_si.html.



 David
Impressive! I like the idea, in special when you can handled derived units and doing conversions like this : convert!(kilo(newton))(2000000 * gram * meter / pow!2(second)));
Mar 22
parent reply Seb <seb wilzba.ch> writes:
On Tuesday, 22 March 2016 at 09:55:28 UTC, Zardoz wrote:
 Impressive! I like the idea, in special when you can handled 
 derived units and doing conversions like this :

 convert!(kilo(newton))(2000000 * gram * meter / pow!2(second)));
Wow that's pretty sweet! So nordlow how about pushing this code to a separate repository and dub? It seems that now there is enough interest in pushing this :)
 I would like to move forward with std.experimental.unit(s).
+1 for pushing this to Phobos!
Mar 29
parent =?UTF-8?B?Tm9yZGzDtnc=?= <per.nordlow gmail.com> writes:
On Tuesday, 29 March 2016 at 12:46:44 UTC, Seb wrote:
 So  nordlow how about pushing this code to a separate 
 repository and dub?
Here you are: https://github.com/nordlow/units-d
Mar 30