Thursday, December 24, 2009

You ARE your operating system (among other things)

Whenever you make a choice among products with similar functions, that choice spills over into the realm of social status.

Cars are a common example where social rank often goes with brand, and even within brand, by model, and even within model, by variations, upgrades, and badges. All signify some social status. I became acutely aware of this after purchasing a car that did not fit my image. It was uncomfortable for everyone.

Your operating system

You can see the social aspect tied to an operating system by looking at the Apple "I'm a Mac" campaign, and the weak Microsoft "I'm a PC" campaign response. A choice to run Linux or other operating system also carries connotations and shared group identity. In this sense, you are your operating system.

Your collection of choices

Whether conscious or not, decisions and choices about purchases you make, where choices are available, weave together part of your social tapestry. The schools you attend, where you work, your clothes, your car, where you live, and yes, your operating system. You are those things, at least socially.

The question is, in the context of a consumer society, can a choice be made without the attachment of social status?

Saturday, December 5, 2009

Calculating the square root of 2 longhand

There are many numerical methods to calculate square roots. This is the long hand method I learned in junior high. It produces one (accurate) digit at a time, but the working numbers get larger each iteration. Eventually, it bogs down because it is doing math with integers hundreds, then thousands of digits long.

Still, it is fun for tinkering. If you run this Ruby script as is, it will calculate the square root of 2 to 1,000 digits. To adjust the precision, change the number of iterations on this line:

while iterations < 1000

Here is the entire script...

#!/usr/bin/ruby
# calculate a square root of 2 using longhand

def newroot(divisor, doubleroot)
# calculate new root
# formula is doubleroot _ * _ = closest to divisor
# try 9, then 8, then 7 ...

i = 9
while i >= 0
multiple1 = (doubleroot.to_s + i.to_s).to_i
multiple2 = i
product = multiple1 * multiple2

if product <= divisor
# found new root
root = i
# get modulus
modulus = divisor - product
break
end
i = i - 1
end


return root, modulus
end

roots = Array.new

# the nearest root to 2 is 1

root = 1
roots.push(root)
remainder = 2 - root

doubleroot = root * 2
divisor = remainder * 100

iterations = 0

while iterations < 1000
root,remainder = newroot(divisor, doubleroot)
roots.push(root)

# compute new doubleroot

return root, modulus
end

roots = Array.new

# the nearest root to 2 is 1

root = 1
roots.push(root)
remainder = 2 - root

doubleroot = root * 2
divisor = remainder * 100

iterations = 0

while iterations < 1000
root,remainder = newroot(divisor, doubleroot)
roots.push(root)

# compute new doubleroot
doubleroot = roots.to_s.to_i * 2

# compute divisor
divisor = remainder * 100

iterations = iterations + 1

print "iteration " + iterations.to_s + "\n"
end

print "final roots are " + roots.to_s + "\n"

Tuesday, November 10, 2009

Root 2: 500 million glyphs

Having generated a text file with the first billion digits of the square root of 2, I started thinking about how to convert it to text.

First Try

My first try was an attempt to convert groups of 2 or 3 digits into a character using the ASCII code table. This was not very straight forward for several reasons. To start, many characters in the range from 0-255 are either non-printable or produce symbols or punctuation. To get around this, I decided to only use the part of the table that started with the numbers and went through the end of the lower case letters.

That left some 2 digits numbers that had to be scaled up into the useful range and many 3 digit numbers (everything greater than 255) had to be scaled down to the range. I did get a script working that accomplished this, but the results were not satisfying.

Second Try

I decided to use a simpler solution and convert each pair of digits into a letter using the range 1-26. To do this, I added one to the modulus of 26 and each digit pair and indexed it into the alphabet. Because 26 does not go into 99 evenly, this produces a slight bias against the last few letters of the alphabet but I was will to live with the result.

As an example, the first two digits are 14. 14 divided by 26 is 0 with a modulus (remainder) of 14. Adding one to 14 is 15 returning the letter O. The next two digits are 14 also returning O. The next two are 21 returning the letter V.

At the end of another scriptaculous ruby adventure, I had converted my billion digit file into 500 million letters.

Signals in the noise

To make the file easy to search, I wrote the resulting text file out in 72 character lines. Yes, this causes some loss of continuity at line breaks, but again, I was willing to live with it.

I quickly found the string with my name "KEITH" 65 times. The first occurrence was 7,398,524 digits into the square root of 2. My wife's name appeared 125 times.

I found "GOD" 33,663 times with the first appearance at 3,186 digits.

As expected, the smaller the text string, the more likely it is to be found. Most words and strings up to 6 characters can be found in the first billion digits of the square root of 2. Strings 7 characters and longer, like "CALIFORNIA" are often not found.

For fun, I ran a few searches for dates and numbers in the integer file, finding things like my birthday and dates of historic events. Numeric strings are much easier to find.

Next, I'll post one of my ruby scripts to calculate the square root of 2 digit by digit. It is very slow and inefficient, but fun for tinkering. I have a few more ideas for grappling with the root of 2.

Friday, October 23, 2009

Root 2: the shallow end of infinity

A couple of months ago, I got the semi-psychotic idea to search for numbers and strings in the digits of the square root of 2. The idea is hardly unique. There has been a fair amount of research into this area, a variation on the infinite monkeys typing on a typewriter theorem.

Why Root 2?

Because it wasn't Pi. Pi is the probably the most studied math constant, so I wanted to start with something fundamental that wasn't pi.

I needed an irrational constant, one that generated an infinite stream of random numbers, and root 2 was as good a choice as any. I might argue that root 2 is even more commonly encountered than pi, in that it is found in the hypotenuse of a 1x1 square. Surely, 1x1 squares are more common than circles in the modern world.

Infinite Integers

The first challenge was to find or generate the integers of root 2. With a quick search, I found up to 10 million digit files that had been created by NASA. While a good start, I wanted a lot more than 10 million digits. I ended up using the 1 million file from NASA as a control file to make sure that any other method I used to generate digits was validated by NASA. My starting target was 1 billion digits, but I wanted the ability to go to an arbitrary number.

When I started thinking about how to generate digits with a computer, I realized there were some unique hurdles in trying to calculate infinite precision numbers. First, standard machine data types fail at the task. 64-bit integers give you a large work space, but floating point numbers are notorious about losing precision. The math libraries of most languages work to about 15 digits, so those were out.

I found more than 10 methods documented to compute square roots.

Baby Steps

The first attempt to calculate the square root of 2 was actually written by a colleague who was intrigued enough to implement the Babylonian method in clojure. The first few tests seemed promising and matched the NASA file up to roughly 25,000 digits. Where it broke down was after about 20 iterations where the run time exceeded 18 hours. Getting to a very large number of digits did not appear to be practical.

The next attempt was one I wrote using the Duplex method (in ruby). Duplex has the advantage of computing one digit at a time and I was hoping this would avoid some of the problems with doing multiplication with millions of digits. There may have been a flaw in my ruby implementation because it got off track past digit 53 when I compared the results with the NASA file. I was careful to follow the example I found in Wikipedia, but I must have made some kind of mistake because it always diverged.

Standing on Shoulders

Like any good programmer, I quickly decided to search for working code that someone else had written. I found a very old C++ implementation, but also a handful of working programs. The one I tried first was PiFast.

PiFast is a Windows program that can calculate many constants in addition to Pi. Since my main computer is a Macbook, I loaded it into my VMware virtual machine running XP. As you might imagine, it was more than a little CPU intensive. After a few short trial runs, I let it loose on a 1 billion digit computation that for all intents locked my machine for about 11 hours. At the end, I had a file of 1 billion digits, the first million of which validated perfectly against the NASA file.

To validate and test the file -- a 1 gigabyte file -- I wrote a number of scripts (ruby is my scripting language of choice these days) to test the digits, and manipulate the file in several ways.

In my next post, I'll talk about how I converted digits to letters and what my early searches turned up.

Friday, September 25, 2009

Introduction to AutoFS in Mac OS X

Note: I originally published this article on Low End Mac

OS X uses an AutoFS code stack based on Sun's Solaris version of Unix. Many of the advanced features are not documented very well, and this can be an issue unless you are familiar with Solaris. I was not and had to do quite a bit of digging.

AutoFS is often used in enterprise environments to set up network-based home directories and other network mounts for users at login. It can also dynamically mount network shares on access.

OS X auto_master and auto_home

The /etc/auto_master file controls the auto-mounted Network File System (NFS) file systems. If you are going to mount NFS volumes from a Linux server, there is one gotcha that I covered in an earlier blog post.

The auto_master defines all "maps" which are collections of automounts related by mount point and organized in one file (or directory service entry). Here is what the default file looks like on my Mac:
#
# Automounter master map
#
+auto_master # Use directory service
/net -hosts -nobrowse,nosuid
/home auto_home -nobrowse
/Network/Servers -fstab
/- -static


The plus (+) sign in front of the auto_master entry tells OS X to look in the directory service (Open Directory, LDAP, etc.) for an automount record and use it if found.

Notice the /home entry is set to auto_home, and because it is not a full path, it is assumed to be /etc/auto_home. It is an example of an indirect map. The mount point in the local directory is defined, but the remote mounts are defined in the /etc/auto_home map file. Network users who login to the local machine will have their home directories mounted in /home according to the details in /etc/auto_home.

Here is the default /etc/auto_home file:
#
# Automounter map for /home
#
+auto_home # Use directory service


Once again, we see the plus sign telling OS X to look for an auto_home record in the directory service. No further details are defined.

The last two lines in auto_master handle NFS mounts defined in the /etc/fstab file, the common file system mount table in Linux and other Unix flavors. The /etc/fstab file is deprecated in OS X and not recommended.

Applying changes to autofs

The automount process will not detect changes made to auto_master or other map files unless you tell it. This command tells the process to read all map files again:

sudo automount -vc

AutoFS wildcards

Wildcards can be used in mount map files to allow directory substitution. For example, if you had this defined in auto_master:

/opt auto_public

And this defined in /etc/auto_public:

* nfs.mydomain.com:/public/&


Then, when /opt/bin was accessed, nfs.mydomain.com:/public/bin would be mounted on /opt/bin. The same would apply for any subdirectory accessed under /opt.

Other Map Types

OS X AutoFS supports direct maps, where the local mount points are defined inside the mount map file, and indirect maps, where the local mount point is defined in auto_master. The wildcard example above is an indirect map. There are also executable maps where the mount map file is actually an executable shell script that returns the names of the mount points within the trigger folder. Exploring executable maps is left as an exercise for the reader. Finally, you can define static maps in /etc/fstab or in the Directory Utility Mounts tab.

Other file system types

All of the examples shown use the NFS file system. OS X autofs can also handle Apple File System (AFP) and Microsoft Server Message Block (SMB) file systems.

To use these file systems, add the -fstype=afp and -fstype=smbfs options when defining the remote mount points. (Note: You cannot use smbfs for remote home directories unless you are using the Microsoft Active Directory service plugin.)

Saturday, June 27, 2009

Playing nice with Linux NFS

I naively assumed that mounting an NFS volume exported by Linux would be uneventful, and it should be. My initial attempt to manually perform an NFS mount failed without any client side error message.

Checking system logs on the Mac revealed nothing.

The Linux NFS server (Red Hat Enterprise 5) complained with this warning:

nfsd: request from insecure port (192.168.7.130:49232)!


After some Internet sleuthing, I found Mac client side NFS tries to mount NFS volumes over high TCP ports (>1024). You must explicitly tell the Linux NFS server to accept mount requests on high ports by adding the "insecure" option to /etc/exports. For example,

/nfstest 192.168.206.0/24(rw,async,insecure)

Then, NFS mounts from OS X should work as expected.

Sunday, April 12, 2009

Automating FTP on the Mac

There is no shortage of GUI FTP programs, but kicking it old school on
the command line allows you to easily automate uploads and downloads.
The best part is, there is nothing to install. Everything you need
waits patiently behind the warm glow of a Terminal session.

The Mac command line FTP program
The default command line FTP program in OS X 10.5 resides at:
/usr/bin/ftp

By all outward appearances and behavior, the Mac FTP program is
the standard BSD version. The man page is the standard BSD
page and contains a wealth of useful information.
A typical command line FTP session is interactive and goes something
like this:

  • login to an FTP server

  • issue commands (ls (list), get (download), put (upload))

  • quit


If you have a repetitive FTP task, the fun quickly fades into a
mind numbing exercise. This is where FTP automation
shines.

The magical .netrc file
What makes FTP automation possible is a magical, little known file
called .netrc. The .netrc file is a plain text file that is
hidden (the file name starts with a period) and lives in the root of
your home directory. The .netrc file allows FTP to perform automatic
logins to FTP servers based on the name.

The .netrc is not created by default. You have to create it manually.
To create an empty .netrc file, open a Terminal and use the following
commands:

touch .netrc
chmod 700 .netrc


It is critical that you issue the chmod command to
set the permissions so that only the owner of the file can view it. If
the permissions are not set correctly, the FTP client will assume it has
been compromised and will refuse to use it.

Inside the .netrc, you define a block of settings for each FTP
server you use, including the machine name, the login ID and the
password. Here is what a typical block for a mythical FTP server:

machine myftpserver.com
login myuser
password mypassword


There are additional settings that can be included. Check the FTP man
page for more. You can test your settings by typing "ftp
myftpserver.com" at a Terminal prompt and it should automatically login.
Note that you can store multiple FTP server logins in the .netrc file.

Sending FTP commands from a BASH shell script
Once logins are automated, the final piece of the puzzle
is to script a set of FTP commands. The following example uses an
advanced BASH shell scripting technique called a "here" document
to group the FTP commands to be sent to the server.

#!/bin/bash
/usr/bin/ftp -d myftpserver.com << ftpEOF
prompt
put "*.html"
quit
ftpEOF


The FTP command is issued with the -d flag (debug mode) to make it more
verbose. That makes any kind of error more obvious. The connection is
made to myftpserver.com using the ID and password from the .netrc file.
Once the connection is made, the rest of the commands are issued one at
a time until the end of the "here" document at the second "ftpEOF". Note
that any valid FTP commands can be sent. In the example, the
prompt command tells FTP not to prompt for multiple file
operations, then the put uploads all files with an html
extension. If you want to go the extra mile, you can extend the shell
script and do things like reconnect to the FTP server to verify the file
sizes of your uploads.

While there are several ways you can automate FTP, the nice thing about
this method is that it is portable to Linux or any other Unix system.

Saturday, March 21, 2009

system_profiler - gathering hardware/software configuration

Another useful command line tool, system_profiler reports detailed information about the hardware and software configuration of the Mac.

It reports the same information you can find in the Apple menu / About This Mac / More Info dialog.

One of the things that makes it so useful is that you can look at the configuration of a system you are connected to remotely, like through a secure shell connection.

There are three details levels available:
  • mini - report with no personal information
  • basic - basic hardware and network information
  • full - all available information
You select which detail level by passing it using the -detailLevel switch. For example:

system_profiler -detailLevel mini

If no detail level is passed, the default level is full.

Because it generates so much information, you typically pass the output to the "less" utility, redirect it to a text file for browsing, or filter out what you are looking for using "grep".

Wednesday, February 25, 2009

Enable/disable Fast User Switching from the command line

To enable fast user switching, use the defaults command from the terminal:


defaults write /Library/Preferences/.GlobalPreferences MultipleSessionEnabled -bool YES


To disable fast user switching:


defaults write /Library/Preferences/.GlobalPreferences MultipleSessionEnabled -bool NO