Time is Neutral

Notes and thoughts on computing, mathematics, and anything else I can write about.

About

Paul English is a student and software developer in Salt Lake City.

Email · Resume

25 November 2014

I tend to work in several git repositories throughout any given day. This means a lot of changes, and a lot of commit messages. Sometimes it's easy to lose track of a few edits or improvements to a repo, and have those changes stay in a local working tree until the next time I revisit a particular piece of code. So I wrote a script that keeps me reminded of unstaged and uncommitted changes.

23 October 2014

I know that Jekyll is supposed to be a coder friendly blogging platform, but sometimes opening yet another buffer in your text editor can be a pain, e.g. when you've got a couple hundred buffers open, you're deep in a project, and you just want to make a short post. I figure if I want to blog more I should oil and smooth out the process. So I wrote a few short functions for setting up a new blog post (I'm sure others have done this too) and helping me publish changes quickly.

Here's what I use to create a new post, you'll probably want to look it over and update it to work for yourself.

(defun wrap-in-quotes (s) (format "\"%s\"" s))

(defun create-new-blog-post (title categories slug)
  "Creates a new jekyll blog post. Assumes a lot about the environment."
  (interactive "sPost title: \nsPost categories (uppercased, comma seperated): \nsPost slug (optional, can be guessed from the title): ")
  (let* ((year (format-time-string "%Y"))
         (date (format-time-string "%Y-%m-%d"))
         (cleaned-title (replace-regexp-in-string "[\'_]" "" title))
         (cleaned-title (replace-regexp-in-string "&" "and" cleaned-title))
         (downcased-title (downcase cleaned-title))
         (slugged-title (if (not (string= slug ""))
                            slug
                            (replace-regexp-in-string " " "-"
                                                      downcased-title)))
         (filename (concat "~/sync/code/blog/_posts/" year "/" date "-" slugged-title ".md"))

         (formatted-categories (mapconcat 'identity
                                          (mapcar 'wrap-in-quotes
                                                  (split-string categories ", "))
                                          ", "))
         (default-content (format "---\ntitle: %s\ncategories: [%s]\nlayout: default\npublished: true\n---\n\nHappy blogging!\n"
                                  title
                                  formatted-categories)))
    (find-file filename)
    (insert default-content)))

I bind it to a keychain just for blogging.

(global-set-key (kbd "s-b n") 'create-new-blog-post)

Next I run a few commands to deploy using ansible.

(defun publish-blog (message)
  "Commits posts in the blog and runs ansible to publish it. Assumes a ton about the environment."
  (interactive "sCommit message: ")
  (let ((default-directory "~/sync/code/blog/"))
    (shell-command "git add .") ;; Careful, you better know what you're committing!!
    (shell-command (format "git commit -m \"%s\""
                           message))
    (shell-command "git push origin master"))
  (eshell)
  (goto-char (point-max))
  (eshell-kill-input)
  (insert "cd ~/sync/code/isospectral/ansible_playbooks/")
  (eshell-send-input)
  (insert "ansible-playbook -i hosts blog.yml -K")
  (eshell-send-input))

Also mapped to a similar hotkey.

(global-set-key (kbd "s-b p") 'publish-blog)

You'll probably want an up-to-date version, which as of the time of this post can be found at my fork of the prelude starter kit.

16 June 2014

Most of the operations on your computer are precise approximations, not real answers. In most cases your computer, which is made up of a finite number of mechanical switches, can only represent numbers with a certain precision. This is usually well known for people who deal with programming, computer science, and in general computation.

One thing that isn't usually tested by most is what this precision actually is. But it's pretty quick to find out. Here's some Clojure code that will do precisely that.

(defn machine-epsilon []
  (loop [k 1 s 1.0]
    (if (or (<= (+ s 1.0) 1.0)
            (> k 100))
      [(dec k), (* 2.0 s)]
      (recur (inc k) (* 0.5 s)))))

The key here is in our comparison (<= (+ s 1.0) 1.0) where we're checking if a positive number s > 0 incremented by 1 is somehow less than or equal to 1. Notice that s begins at one and is divided by 2 (through multiplication) at each step, logically it should always be a positive non-zero value. In a pure math sense this algorithm should never finish (aside from our termination condition k). This algorithm literally runs till our machine makes a mistake in it's finite precision arithmetic. Our number s gets too small to handle correctly and is effectively treated as zero (or possible a negative value) so we stop and return the value we had where we know arithmetic still worked. Try it out, this algorithm can be set up in just about any language and on any platform. It was adapted from a simple pseudocode example in "Numerical Analysis" by Kincaid & Cheney.