When dealing with random numbers, one often needs to get a random floating point number between 0 and 1 (not inclusive). Unfortunately, most random generators only deal with integers and/or bytes. Since bytes can be easily converted to integers, question becomes: “How can I convert integer to double number in [0..1) range?”
Well, assuming you start with 64-bin unsigned integer, you can use something like this:
Code
ulong value = 1234567890; //some random value byte[] buffer = BitConverter.GetBytes((ulong)0x3FF << 52 | value >> 12); return BitConverter.ToDouble(buffer, 0) - 1.0;
To understand this code, you need to know how doubles are encoded. The first bit is sign and we can ignore it for this usage. 11 bits that follow belong to exponent and setting them all to 1 means we start at 2⁰ (aka 1). The remaining bits express fraction portion of the floating-point number.
With that in mind you you can see that 8-byte (64-bit) buffer is filled with double format combined of (almost) all 1's in exponent and the fraction portion containing random number. If we take that raw buffer and convert it into a double, we’ll get a number in [1..2) range. Simply substracting 1.0 will place it in our desired [0..1) range. It’s as good as distribution of a double can be (i.e. the maximum number of bits – 56 – are used).
This is as good as uniform distribution can get using 64-bit double.
PS: If we apply the same principle to the float, equivalent code will be something like this (assuming a 32-bit random uint as input):
Code (single)
uint value = 1234567890; //some random value byte[] buffer = BitConverter.GetBytes((uint)0x7F << 23 | value >> 9); return BitConverter.ToSingle(buffer, 0) - 1.0;
PPS: C#’s Random class uses code that’s probably a bit easier to understand:
Code (C# random)
return value * (1.0 / Int32.MaxValue);
Unfortunately, this will use only 31 bits for distribution (instead of 52 available in double). This will cause statistical anomalies if used later to scale into a large integer range.
For one of my hardware projects, I decided to try doing things a bit differently. Instead using a single repository, I decided to split it into two – one containing Firmware and other containing Hardware.
Since repository already had those as a subdirectories, I though using --subdirectory-filter as recommended on GitHub would solve it all. Unfortunately, that left way too many commits not touching either of those files. So I decided to tweak procedure a bit.
I first removed all the files I didn’t need using --index-filter. On that cleaned-up state I applied --subdirectory-filter just to bring directory to the root. Unfortunately, while preserving tags was possible, it proved to be annoying enough to actually remove them all and manually retag all once done.
As discussed above, on the COPY of original repository we first remove all files/directories that are NOT Hardware and then we essentially move Hardware directory to the root level of newly reorganized repository.
With Hardware repository sorted, I did exactly the same process for Firmware with the new COPY of original repository, only changing the directory names.
Surface Go is almost a perfect Ubuntu machine. The only reason for “almost” being the lack of camera support. All else works out of box or with minor updates. While you can use the standard installation setup, I like to do it in a bit more involved setup.
Mind you, you will need to have a network adapter plugged during install as debootstrap requires it and enabling wireless is one of things not working out of box. If that’s the problem, stick with the default install instead.
First you of course you need to boot from install USB. After booting into Ubuntu desktop installation one needs a root prompt. All further commands are going to need root credentials anyhow.
Terminal
sudo -i
Now we can set a few variables – disk, pool, host name, and user name. This way we can use them going forward and avoid accidental mistakes. Just make sure to replace these values with ones appropriate for your system.
Disk setup is really minimal. If there was a chance of dual-boot, EFI partition would be too small. For multiple kernels, one would need to increase boot partition. However, considering Surface Go has 64 MB or disk space, keeping those partitions small is probably a better choice. And no, you cannot make EFI partition smaller than 32 GB despite not needing more than a few megs.
Having boot and EFI partition unencrypted does offer advantages and having standard kernels exposed is not much of a security issue. However, one must encrypt root partition.
Since we’re dealing with encrypted data, we should auto mount it via crypttab. If there are multiple encrypted drives or partitions, keyscript really comes in handy to open them all with the same password. As it doesn’t have negative consequences, I just add it even for a single disk setup.
Finally we install out GUI environment. I personally like ubuntu-desktop-minimal but you can opt for ubuntu-desktop. In any case, it’ll take a considerable amount of time.
Terminal
tasksel install ubuntu-desktop-minimal
Short package upgrade will not hurt.
Terminal
apt update ; apt dist-upgrade --yes
The only remaining task before restart is to create the user, assign a few extra groups to it, and make sure its home has correct owner.
Before finishing it up, I like to install Surface Go WiFi and backlight tracer packages. This will allow for usage of wireless once we boot into installed system and for remembering light level between plugged/unplugged states.
After the reboot you should be able to enjoy your installation. Seeing errors is fine – just reboot manually if stuck.
Terminal
reboot
Once booted I like to setup suspend to react on power button and and to disable automatic brightness changes.
Terminal
gsettings set org.gnome.settings-daemon.plugins.power button-power 'suspend' gsettings set org.gnome.settings-daemon.plugins.power power-button-action 'suspend' gsettings set org.gnome.settings-daemon.plugins.power ambient-enabled 'false' gsettings set org.gnome.mutter experimental-features "['x11-randr-fractional-scaling']"
My preferred scale factor is 150% (instead of default 200%) but you’ll need to change that in settings manually.
I had an interesting problem. I wanted another monitor. But I didn’t want to buy it. For one, I just needed it just temporarily. Secondly, I needed it to be mobile so any properly sized monitor was out of question.
With that in mind, I took inventory of things I had and came upon an idea. I already have HDMI capture USB and I already have Surface Go which surely looks like a mini monitor. If I connect my laptop via HDMI to the capture card and use webcam to show capture output, I essentially have an HDMI-to-monitor connection.
I tried it and it worked wonderfully. Almost.
As my Surface Go runs Ubuntu, I have tried multiple Linux webcam applications and neither of them worked as I wanted. I simply could not find any that would work in full screen. In addition to losing screen real estate, I also noted other issue – darn cursor was visible. None of the webcams would turn off cursor while running.
After going over every webcam application I could find and finding a fault for each, I finally decided to build my own.
This is as simple as webcam software gets. When started, it will display the first webcam while keeping cursor hidden. If you press Space, it will switch to the next webcam. Essentially everything I needed.
And yes, I did complicate it a bit more later. I added a support for windowed mode, going as far to allow alignment to any screen corner (try keys 0–9) so you can have “head-in-the-corner” effect. I also added a few configurable settings and will probably add a few more with time. However, the idea is to keep it as simple as possible.
Application supports both Linux and Windows. If you’re in need for something like that, give it a try.