{"id":13409537,"url":"https://github.com/HeisenbugLtd/si_units","last_synced_at":"2025-03-14T14:31:31.564Z","repository":{"id":108361227,"uuid":"240281613","full_name":"HeisenbugLtd/si_units","owner":"HeisenbugLtd","description":"Utility library to pretty print physical values in proper metric units","archived":false,"fork":false,"pushed_at":"2020-10-19T09:24:41.000Z","size":127,"stargazers_count":8,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-07-31T20:37:13.104Z","etag":null,"topics":["ada","ada-language","ada2012","convenience","digits","distance","formatting-output","instantiation","physics","pressure","scale","si-units","subprograms","utility-library"],"latest_commit_sha":null,"homepage":"https://github.heisenbug.eu/si_units/","language":"Ada","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"wtfpl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/HeisenbugLtd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-02-13T14:36:13.000Z","updated_at":"2024-02-15T21:14:45.000Z","dependencies_parsed_at":null,"dependency_job_id":"cf425d72-7b44-4322-87dd-a8bc52e04782","html_url":"https://github.com/HeisenbugLtd/si_units","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HeisenbugLtd%2Fsi_units","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HeisenbugLtd%2Fsi_units/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HeisenbugLtd%2Fsi_units/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/HeisenbugLtd%2Fsi_units/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/HeisenbugLtd","download_url":"https://codeload.github.com/HeisenbugLtd/si_units/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243593454,"owners_count":20316187,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ada","ada-language","ada2012","convenience","digits","distance","formatting-output","instantiation","physics","pressure","scale","si-units","subprograms","utility-library"],"created_at":"2024-07-30T20:01:01.743Z","updated_at":"2025-03-14T14:31:28.797Z","avatar_url":"https://github.com/HeisenbugLtd.png","language":"Ada","funding_links":[],"categories":["Libraries"],"sub_categories":["Science"],"readme":"![SI Units](https://raw.githubusercontent.com/HeisenbugLtd/heisenbugltd.github.io/master/assets/img/si_units/cover.png)\n\nUtility library to pretty print physical values in properly scaled\n[metric (SI) units](https://www.nist.gov/pml/weights-and-measures/metric-si/si-units).\n\n[![Build Linux](https://github.com/HeisenbugLtd/si_units/workflows/Build%20Linux/badge.svg)](https://github.com/HeisenbugLtd/si_units/actions?query=workflow%3A%22Build+Linux%22)\n[![Alire](https://img.shields.io/endpoint?url=https://alire.ada.dev/badges/si_units.json)](https://alire.ada.dev/crates/si_units.html)\n\n### Problem\n\nAssuming you're writing software that deals with real world values (like\nfrequency, speed, distance, pressure, etc. pp.), at some point you probably\nwant to print values of such types.  To be nice to the user, such values should\nbe properly formatted.  Ada provides formatting libraries (like\n`Float_Text_IO`, or even the simple `'Image` attribute) for that purpose, but\nthese do not scale input values, they plainly output whatever you give them in\nwhatever formatting you requested.  So, if you are using a base value of \"m\"\nfor your distance type, a distance of 42.0 km will be output as something like\n\n`42000.000`\n\nby some properly instantiated `Text_IO` package.  Often this is still quite\nunsatisfactory, especially when dealing with very large or very small values,\nso that representations with exponents (like `42.424242E-9`) will be used by\ndefault.  So, what do you do?  Wrap up your own formatting subprograms, right?\nNo, of course not, not anymore! Instead ...\n\n### Solution\n\n... **Use SI_Units!**  It provides several `Image` function generics for\nformatting such values.  What it does, is that it takes the given value into\nconsideration before converting it into a string and returning an appropriately\nformatted string including the prefixed physical unit.\n\n### Compiling SI_Units\n\nSI_Units is designed as a library to be linked statically.  For this purpose, a\nlibrary project is provided:\n\n```sh\ngprbuild -P si_units.gpr\n```\n\nBy default this builds an optimized version of the library with all runtime\nchecks enabled.  After compilation succeeded, you can install the library in\nyour `gnat` installation like this:\n\n```sh\ngprinstall -p -P si_units.gpr\n```\n\nDepending on how your GNAT installation is set up, the latter command may\nrequire elevated privileges to write into the installation directory, so if\nneeded, prepend sudo \u003c/path/to/gnat/installation/\u003e/bin/ to the gprinstall\ninstruction above.\n\nAfter that, all you need is to add the line `with \"si_units\";` to your\nproject file and you're ready to go.\n\n#### Tests\n\nYou can also build the tests, these are provided in the `test` subdirectory:\n\n```sh\ngprbuild -P test/si_units_test.gpr\n```\n\nAfter that, an executable `./test/obj/main_si_units_test` should have been\ncreated which you can run. It should spit out something like\n\n```\nTest results: 9440 out of 9440 succeeded.\n\u003cOK\u003e\n```\n\nIf you haven't changed anything in the provided sources, yet the last line of\nthe output does not say `\u003cOK\u003e`, but rather `\u003cFAILED\u003e`, you should report a bug.\n\n### Examples\n\nSo, in the example from the introductory paragraph, you would first instantiate\nan appropriate `Image` subprogram for your `Distance` type:\n\n```ada\nfunction Image is new\n   SI_Units.Metric.Float_Image (Item        =\u003e Distance,\n                                Default_Aft =\u003e 3,\n                                Unit        =\u003e SI_Units.Meter);\n```\n\nThis instantiates the subprogram `Image` for the type `Distance`, the default\nnumber of digits after the decimal point will be `3` and the unit name is `m`\n(meter).\n\nThen you can call this `Image` instantiated for your `Distance` type like this:\n\n```ada\nAda.Text_IO.Put_Line (Image (42000.0));\nAda.Text_IO.Put_Line (Image (4200.0));\nAda.Text_IO.Put_Line (Image (420.0));\nAda.Text_IO.Put_Line (Image (42.0));\nAda.Text_IO.Put_Line (Image (4.2));\nAda.Text_IO.Put_Line (Image (0.42));\nAda.Text_IO.Put_Line (Image (0.042));\nAda.Text_IO.Put_Line (Image (0.0042));\nAda.Text_IO.Put_Line (Image (0.00042));\n```\n\nand you'll get:\n\n```\n42.000 km\n4.200 km\n420.000 m\n42.000 m\n4.200 m\n420.000 mm\n42.000 mm\n4.200 mm\n420.0 µm\n```\n\nNeat, isn't it?\n\n`Default_Aft` is merely provided for convenience, the number of digits after\nthe decimal point can be specified for each call to `Image`:\n\n`Ada.Text_IO.Put_Line (Image (4200.0, Aft =\u003e 1));`\n\nwill output\n\n`4.2 km`\n\ninstead.\n\n### (More) Examples\n\nYou may have noticed that the instantiation above used a package name\n`SI_Units.Metric`.  Now, if you'd expect a child package named `Imperial`,\nyou'd be wrong.  After all, the library is called \"SI Units\", so sorry, I am\nnot supporting things like *foot pound per square inch*.  But, besides decimal\nprefixes (what it usually called \"metric\"), there's also an official definition\nfor binary prefixes, good for your Megabits/s (Mebibits/s) connection speed and\nyour Terabytes (Tebibytes) of storage.  So yes, the other child package\nhierarchy is `SI_Units.Binary` and provides a similar[1] functionality for\nvalues that are better written with binary prefixes:\n\n```ada\nfunction Image is new\n  SI_Units.Binary.Mod_Image (Item        =\u003e Transmission_Speed,\n                             Default_Aft =\u003e 1,\n                             Unit        =\u003e \"byte/s\");\n```\n\n### Scaling support\n\nSometimes, dealing with inputs from external sources means that values come in\ndifferent scales than the ones you're using internally.  For instance, the\n[JSON API from openweathermap.org](https://openweathermap.org/api) returns the\natmospheric pressure in hPa (hecto-Pascal), not in the base unit Pa.  Also, SI\ndefines kg as the base unit, not g(ram), so if you're using values in kg within\nyour program, you may need to convert such values to the prefixless version\nbefore feeding it to their respective `Image` subprogram.\n\nWe got you covered, `SI_Units.Metric.Scaling` does that for you.  Actually from\nany prefix into any other prefix.  So, if you need to convert a value given in\nkm into a value in mm, this got you covered.  Just be careful, you may easily\nexceed the defined range of your type if you scale it around like a mad person.\n\n### Unit names\n\nUnit names given in instantiations are standard strings, except for a tiny,\nlittle `Dynamic_Predicate` that states it can either be completely empty or\nshall not start with control characters or white space.  For any proper use,\nthis predicate can be ignored.  I can't think of any use case that would\nwarrant the use of a vertical tab between the value and the actual unit.  In\nfact, the `Image` subprograms are designed to work in a way that both will be\nseparated by a non-breaking space for better readability and to conform to what\n[SI has to say about it](https://www.nist.gov/pml/weights-and-measures/writing-metric-units).\n\nFor your convenience, all the names of the SI defined physical units are\ndeclared in `SI_Units.Names`.\n\n\n[1] There are no SI prefixes defined for absolute values less than one, so the\nsupport for binary images is currently restricted to natural numbers.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHeisenbugLtd%2Fsi_units","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FHeisenbugLtd%2Fsi_units","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FHeisenbugLtd%2Fsi_units/lists"}