Monday, October 07, 2013

Print bit representation of a signed integer in Common Lisp

So, how do you print the bits of a signed integer in Common Lisp? Easy enough:

(defun print-bits (n)
  (let ((*print-base* 2))
    (print n)
    (values)))

> (print-bits 10)
1010

Or

(defun print-bits (n)
  (format t "~B" n)
  (values))

> (print-bits 10)
1010

But what happens if you try to print a negative number?

> (print-bits -10)
-1010

Not exactly what we were looking for -- we were looking for the bit representation of this number in two's complement form, which is how logical operations treat integers in Common Lisp. So how do we print the bits in two's complement form? The trick is to use ldb. ldb returns a non-negative integer with the exact bits that were contained in the given integer, be it positive or negative.

(defun print-bits (n size)
  (format t "~B" (ldb (byte size 0) n))
  (values))

> (print-bits -10 8)
11110110

> (print-bits -1 16)
1111111111111111

where size is the number of bits that we want to print. Note that you need to be careful about size since this will truncate the printed bits if integer can't be represented in size bits.

Bonus: How do you pad this binary representation to the given size with zeroes on the left for positive numbers? (negative numbers are already padded)

(defun print-bits (n size)
  (format t (format nil "~~~D,'0B" size) (ldb (byte size 0) n))
  (values))

> (print-bits 1 4)
0001

> (print-bits 1 8)
00000001

> (print-bits -1 16)
1111111111111111

Labels: , ,



Saturday, July 27, 2013

A neat reader trick for DO/DO*

So instead of using LOOP every time I needed to use a general purpose looping construct, yesterday I decided to give DO/DO* a shot. The biggest problem that I had with DO was code repetition when the step-form and init-form of an iteration variable were to be the same. For example:

(defun alignment-octets (encryption-fn)
  (let ((block-size (find-cipher-block-size encryption-fn))
        (octet-1 65)
        (octet-2 66))
    (do* ((test-input-1 (make-octets block-size :initial-element octet-1))
          (test-input-2 (make-octets block-size :initial-element octet-2))
          (change-index 0 (1+ change-index))
          (mismatch-start (mismatch (funcall encryption-fn test-input-1)
                                    (funcall encryption-fn test-input-2))
                          (mismatch (funcall encryption-fn test-input-1)
                                    (funcall encryption-fn test-input-2)))
          (mismatch-end (mismatch (funcall encryption-fn test-input-1)
                                  (funcall encryption-fn test-input-2)
                                  :from-end t)
                        (mismatch (funcall encryption-fn test-input-1)
                                  (funcall encryption-fn test-input-2)
                                  :from-end t)))
         ((= block-size (- mismatch-end mismatch-start))
          (subseq test-input-1 0 change-index))
      (setf (aref test-input-2 change-index) octet-1))))

See the iteration vars MISMATCH-START and MISMATCH-END above. I spent some time thinking about how this could be avoided. It didn't seem like DO itself would help us much here. Maybe MACROLET would help, but the solution would probably not be very clean or readable. This seemed like a dead end. However, the Common Lisp reader has a trick up its sleeve -- the dispatch macro character constructs #n= and #n#. To put it simply, if any s-expression is prefixed with #n= (where n is an unsigned decimal integer), then the Lisp reader will replace any corresponding #n# with this s-expression. To be more accurate, the reader treats #n# as a pointer to the same(eq) object that is labeled by #n=.

Let's see this in action:

(defun alignment-octets (encryption-fn)
  (let ((block-size (find-cipher-block-size encryption-fn))
        (octet-1 65)
        (octet-2 66))
    (do* ((test-input-1 (make-octets block-size :initial-element octet-1))
          (test-input-2 (make-octets block-size :initial-element octet-2))
          (change-index 0 (1+ change-index))
          (mismatch-start #1=(mismatch (funcall encryption-fn test-input-1)
                                       (funcall encryption-fn test-input-2))
                          #1#)
          (mismatch-end #2=(mismatch (funcall encryption-fn test-input-1)
                                     (funcall encryption-fn test-input-2)
                                     :from-end t)
                        #2#))
         ((= block-size (- mismatch-end mismatch-start))
          (subseq test-input-1 0 change-index))
      (setf (aref test-input-2 change-index) octet-1))))

An elegant solution to a not so simple problem. Now try this in your favourite language!

Labels: , ,



Thursday, May 10, 2012

A git diff driver for core data model files

Whenever you make a bunch of changes to core data model (xcdatamodel) files, its impossible to know with git diff, what exactly changed. Usually, the output looks like:

diff --git a/Recipes.xcdatamodel/elements b/Recipes.xcdatamodel/elements
index 35a20f3..939bc61 100644
Binary files a/Recipes.xcdatamodel/elements and b/Recipes.xcdatamodel/elements differ
diff --git a/Recipes.xcdatamodel/layout b/Recipes.xcdatamodel/layout
index 052f0e8..18906a4 100644
Binary files a/Recipes.xcdatamodel/layout and b/Recipes.xcdatamodel/layout differ

Git, however, provides a way to diff binary files as if they were text. Using a diff driver and a binary to text converter[1], we can control git's diff output so that we get this:

diff --git a/Recipes.xcdatamodel/elements b/Recipes.xcdatamodel/elements
index 35a20f3..939bc61 100644
--- a/Recipes.xcdatamodel/elements
+++ b/Recipes.xcdatamodel/elements
@@ -2,8 +2,8 @@ Entity: Image (NSManagedObject)
   Att: image                     Transformable                                            O   dafQGIhBFATAxE1hyQd5z5cpRg0OLP4+M+W3+xhA6jU=
   Rel: recipe                    Recipe          image                            Nullify   I fVH2lmmkHE4j/FvzfJ2et3KsNxcA8p5BJp2d/xd4hH0=
 
-Entity: Ingredient (Ingredient)                                                               5tCLlA1r9p1UWdOTr3XJ+ZzBr6bxraWAs3Vt9zCAZek=
-  Att: amount                    String                                                   O   b9/jjR2iJtm4oldVJwj25X+/hpEL6/1CM5hLhgV48Iw=
+Entity: Ingredient (Ingredient)                                                               7nbTTDaWG1lAddHYHum4xP4IA/N90NYv9GLkGK+sueQ=
+  Att: amount                    Integer16                                                O   RmH9Sk61kxsb8+GUEqlEkIuV4tDjxxhMNsHUu/tBW6I=
   Att: displayOrder              Integer16                                                    kMPJ+qU+fnBipO5Ajep+KT3rKB9zeOPrav0q4rMSt7k=
   Att: name                      String                                                       jLmWXAAxrGiROYTzEQlBrZZTlb6f2bF9575UvHrUaJA=
   Rel: recipe                    Recipe          ingredients                      Nullify O I GvmjTsOh76OGkr0Lmnxdh8u6FO4E+iuEYa0mRZPuKJQ=
diff --git a/Recipes.xcdatamodel/layout b/Recipes.xcdatamodel/layout
index 052f0e8..18906a4 100644
Binary files a/Recipes.xcdatamodel/layout and b/Recipes.xcdatamodel/layout differ

The great thing is that, this works not only for git diff, but any git command which displays diff output e.g. git log -p, git show, etc.

To do this for your own iOS or Mac OS X projects, try XCDataModelPrinter -- a small little project I wrote. The README should help you get started. If you have any questions, drop me a message at mail at chaitanyagupta dot com.

1. This technique is explained eloquently in the book Pro Git

Labels: ,



Thursday, April 08, 2010

Adidas miCoach Review: Week 4

This is week 4 of my four week review of Adidas miCoach. Read the whole series here.

After my rant last week about the inability to create custom interval workouts on miCoach, I got a nice little comment on the post to checkout a new custom workout builder "next" week. Well well, come this week and I got this and more:

Custom workout builder

One of the two most useful additions to the miCoach website, this one completely fixes my issues with the interval workouts from last week. Here's a quick rundown on building a custom interval workout:

Select your workout type

Then you define your interval workout. You can set the warmup/cooldown sections and upto 8 different kinds of interval sections. You also need to set the number of repetitions for the interval sections.

An overview of what your heart rate zones for the workout will look like, and you are done.

This is almost perfect for my needs. One thing which will make it even better is that if one could also set the "duration" for the interval sections in terms of distance and not just time. But overall, its a job well done and its dead easy to define your own interval workouts.

Forum

Another welcome addition is the brand new forum. There's the "help" section and then there's the "talk" section -- the former to seek help regarding the device or the website (presumably there would be some admins there), and the latter for general discussion around running and the device (I am sure there will soon be a few bragging contests around people's running "achievements" :P )

Achievments

A novelty feature, mostly. But certainly makes you feel good!

Add/edit routes

Another new addition is that you can pin your routes on a map (via Google Maps). You can supposedly add ratings, notes, etc. This is something I haven't really used much yet, so can't say much about it. I guess I'll add some of my running routes in Gurgaon and Jalandhar at some point of time.

Conclusion

I was a little low on running mileage this week -- managed only a short interval workout on one of the weekdays and then an 18K run on Sunday. All in all, I've put in nearly 90 km worth of outdoor running (not counting treadmill runs in the gym) in the last four weeks (I know its not much -- will have to gradually increase my mileage again), and I have come away quite impressed with the product. Some of the more useful things for me have been:

Another way I benefited from this device was that I picked up my running momentum again. Since I had no major upcoming events to run in since the Mumbai marathon in Jan, I had slacked off quite a bit on running in February. Thanks to the obligations placed by the miCoach contract, running is back on track :) Hopefully things will continue to get better.

Labels: , ,



Wednesday, March 31, 2010

Adidas miCoach Review: Week 3

This is week 3 of my four week review of Adidas miCoach. Read the whole series here.

Update 1: (7th April, 2010) One of my primary rants against the miCoach website in this post -- the inability to define any custom interval workouts -- is now taken care of after a recent upgrade. More in week 4.

After two weeks of miCoach usage, I have been fairly impressed by the stats and graphs that it provides. Its great fun to drool over the graphs -- especially after a good run. Not only that, the information captured by the device is quite granular -- down to once every few seconds. This is probably more than what you need, but still its good to have it.

But what about the "coaching" part of miCoach? As I have said before, for the long runs, where I run easy for a period of 1:30-2:00 hours, I haven't really found the coaching very useful -- for those runs I just find the stats collection useful. Even for short runs which I run at a moderate pace, I don't really use the coaching function.

However, there is one kind of workout which I still hadn't tried with miCoach (and its something that I hadn't done in months) -- the interval workout.

Interval workout

Essentially, in an interval workout, you run for a short period of time at a fast pace, and then slow down (could be even to a brisk walk) to recover. This cycle is repeated a certain number of times. Doing intervals brings a nice variation to an otherwise uneventful routine, plus it also helps build pace and strength.

Now, the miCoach website does provide some interval training routines in its custom workouts. I picked one of them and went for a run. Here's the graph for the run:

For this workout, the coaching function actually did turn out to be quite useful. The plan that I selected was a time based interval training workout -- run at an easy pace for a few minutes, then run hard and fast for a minute, and recover and repeat. Thanks to the attached earphone, I was getting constant feedback about when to slow down or speed up -- didn't have to worry about looking at my watch all the time. One minor annoyance has been keeping the earphone in place when running fast, but I think that is something which can be taken care of.

As I had mentioned in the week 1, its a shame you can't really "customize" the custom interval workouts. The kind of routines they have provided are good, but its too limited. Too bad, 'cause miCoach really shines here.

Not just for running

I thought it would be fun to try it out while doing some physical activity other than from running. Occasionally, instead of taking the lift, I take the stairs to reach my office on 14th floor. One day, I strapped on miCoach before doing so, and here's what it says about my heart rate:

The heart rate monitor atleast, could turn out to be useful for workouts other than running, if its that important to you. Maybe I'll try it in the gym someday.

Long Run

Sunday was, as usual, long run day. I had originally planned to do a 20K run this time but could only manage 15. Maybe it was the evening weather which affected my run, or maybe the oncoming summers were to blame. Maybe it was just an off-day. I was also consistently feeling very thirsty throughout the run, which was a bit baffling. Anyways, I did, again record stats for the entire run using miCoach. But I haven't been able to find the time to upload the workout details yet (thanks, again, to the fact that they have no utility for Linux).

Tau Devi Lal Bio-Diversity Park, Gurgaon

So conclusion from this week has been that miCoach is great for interval training workouts. Unfortunately the number of interval workouts on the website are very limited. If they were to increase that number, or, better still, allow their users to define their own workouts, it would be awesome.

Labels: , ,



Tuesday, March 23, 2010

Adidas miCoach Review: Week 2

This is week 2 of my four week review of Adidas miCoach. Read the whole series here.

Continuing with my ongoing review of the miCoach, I did a couple of outdoor runs this week -- a difficult 8K in the getting-really-hot afternoon sun and then hit the road for late Sunday morning for a good 15K.

As I mentioned last week, I would try adjusting the heart rate settings and see if I could stay in the "zone" a little more than last week. The factory HR settings seemed fine to me, so I reverted to that. And here are the results:

So I stayed a lot above the green zone again (which was my target zone for the run), although the pace was fairly easy (maybe the HR was high due to the sun). I have decided not to focus too much on this zone business for plain and simple runs for now. I will also try to squeeze in an interval training run this week to see how my heart rate varies with it.

Achievements, history and training journal

A few other niceties I discovered on the website:

Achievements

This comes with the Dashboard view (which gives a summary of the latest workout) -- shows "lifetime" achievements for five of the parameters that it tracks: time, calories, distance, heart rate and pace.


History

Bar graphs showing historical running time, grouped by either year, month, week or day.


Training journal

A list view for the completed workouts -- loads of information in a compact view. Nice.


Workout export and backups

One issue that I do have with the webiste at the moment is that there doesn't seem to be anyway for me to export or backup all the workout data that I am uploading here. While Adidas has done a great job with the website, I am not too happy about not having any local backup of my workout data. And if the website doesn't remain upto the mark later on, it will be good to have an alternative (I don't see why Adidas would make this easy to happen though).

Linux support

I complained to Adidas via their feedback link about the lack of Linux support. Got a response back (the same day) that they don't support Linux for now and the "suggestion will be passed on to the responsible department". Guess that means nothing for now :( If you are a developer who works on miCoach you would have one very grateful customer if we saw Linux support soon!

Stride sensor battery issue

One issue I have encountered a few times now is that when the it is switched on, Pacer refuses to detect the stride sensor until I take out the stride sensor's battery and put it in again. This is really annoying if I have to do this everytime I need to use miCoach. I wrote to Adidas about it and they replied back that this might either be an issue with low battery or with pairing.

What's next?

So my training log shows that I have done about 43K worth of outdoor running in the last couple of weeks. That's a bit on the lower side -- but then again, summers are here! Still, I want to hit the 100K mark for four weeks, so I will be aiming to do about 60K worth of running in the coming two weeks. I will also try to squeeze in a couple of interval training sessions and hope that miCoach's "coaching system" will prove a little more useful here.

Labels: , ,



Tuesday, March 16, 2010

Adidas miCoach Review: Week 1

This is week 1 of my four week review of Adidas miCoach. Read the whole series here.

(Update 1: Linked to the Drizzlin Media website upon their request)

About a month back I was contacted by Adidas via a branding consultancy to review the miCoach Pacer -- an interactive, personal coaching system for runners (Garmin Forerunenr and Nike+ are others that come to mind). Personally, I never really gave a serious thought to using a device like this to aid my running, but now that an opportunity presented itself I didn't mind checking it out first hand.

Essentially the deal is that I review the device for four weeks (which means a blog post a week for a month), writing about my experiences with the thing, and then I get to keep the device to myself. Some PR for them in return for keeping the device for free -- fine by me, as long as they have no problems with me writing either a good, bad or an ugly review (which I have been assured is the case, and in any case it all goes up uncensored on my blog). This post forms the first of these reviews.

How miCoach works

So what does the device do? As a monitoring device, it measuers two things -- your heart rate and your stride rate. So there's a heart rate monitor which you strap on to the chest and a pedometer which goes into your shoe. Then there's the "Pacer" itself -- the central processing unit which (wirelessly) collects data from the sensors and gives you real-time audio feedback about various things like distance, calories, pace, etc.

You connect your headphones to the Pacer to get audio feedback (the device ships with one). You can also connect the output of your music player to the device, so you can listen to music while running. I personally don't listen to any music while running -- wearing headphones while running seems to be a hassle to me. So needing to wear a headphone all the time for feedback is a bit irritable. Wish they had attached a loud speaker to this thing ;)

In addition to monitoring your running stats, you can also plan beforehand what kind of a workout you are going to do -- like a hard short run or an easy long one. Then store the workout details in the device and let the device (in a pleasant British female voice) give you feedback on how well you are doing.

miCoach package and gear
Chest strap, heart rate monitor, stride sensor and pacer

To better understand this, its important to know that the one thing that is central to training with miCoach is that they have this concept of heart rate (HR) "zones":

So I could, say, schedule a workout beforehand to do a relatively easy run in the green zone for a few kms. When I am actually running, the device would tell me to slow down or speed up if my heart rate deviates from the normal range for this zone (more on this later).

Ultimately, you sync all this data to your account on the miCoach website where you get nice looking graphs and stats for your run (that is where you schedule custom workouts too). AFAIK, there's no desktop software to do the same -- as they say, its all in the cloud. So, the miCoach website becomes an important part of your experience with the device. I will discuss the website itself in a bit more detail.

Syncing the device is easy enough -- you plugin a USB cable into your PC (provided with the device) and download a desktop utility to sync the device to your miCoach account. As expected, while the utility is available for Windows and OS X, there's nothing for us Linux users :( Which is a shame, since I think the utility itself is written in Java -- they shouldn't have much trouble porting it to Linux. Hope someone from Adidas reads this, and puts out a binary for Linux too; till then, its booting into Windows everytime I need to sync the device, which is a royal PITA.

Website review

Alright, enough ranting about OS compatibility -- its not as if a lot of Tux users are interested in running anyways :P Time to get down to reviewing the website (http://adidas.com/micoach) itself a bit.

The website (warning: Flash alert), although it does have its shortcomings, is surprisingly quite usable. Adidas seems to understand the importance of the website w.r.t the overall miCoach experience, and has put in a good bit of effort to make it easy and enjoyable to use.

Sign up and settings

Sign up is not much of a hassle except for the need to confirm your email address.

As far as settings go, you can control units of measure (imperial or SI), adjust your designated heart rate zones, select what information kind of information you want to be fed back to you via audio while running, etc. Probably a good idea to give your bio stats like gender, height and weight to get a better idea about your calorie count (atleast that's what the website says).

Heart rate adjustment settings

Plans and Schedule

A few pre-defined training plans are provided, each of which consists of a few weeks worth of workouts for you. That's not my kind of thing, so I define my own custom workouts and run accordingly.

There's a nice calendar which displays past and upcoming workouts.

Workout calendar

Creating custom workouts is a bit disappointing though. You can define time based workouts and distance based workouts -- and you can set one intensity level at which you want to complete this time or distance based workout. That's about it though -- you don't get much more flexibility than that. What if I want to define a 10K workout wherein I want to run the first 5K in green zone, and the next 5K in yellow? Fat chance; you can't do that. What if I want to schedule a fartlek (which I think would go very well with miCoach's concept of heart rate zones)? Don't see any option for that either.

Its a shame because this severely limits the custom workouts feature -- without that flexibility I don't think I'll get to use this much. And while there's an "Interval" workout, its just another set of pre-defined workouts which might or might not suit me -- I have no way of modifying them.

Workout stats

This is the most fun part. After you've completed a workout, sync up your workout stats on the cloud and then you get to gaze over some nice looking graphs. Summary includes your total time taken, calories consumed and distance covered. There's also average heart rate, pace and stride rate.

And then of course, you can see detailed graphs about your heart rate, pace or stride rate as a function of time or distance. There's also a nice overlay view in to compare two quantities together. e.g. my HR and pace graphs for Sunday's 12K run overlaid over each other (HR -- dark line, pace -- light line):

HR and pace graphs for 12K run

One interesting fact I discovered was that my stride rate remains quite consistent over a good range of running speed, averaging 162-164 strides per minute.

As far as accuracy of measurements go, I can't say much about the heart rate as I've never used a heart rate meter while running before. I think the pedometer should be fairly accurate while computing the stride rate. One thing that I did have my doubts on, but which turns out to be quite accurate is the distance calculated by the pedometer (also called Stride sensor by Adidas). For example, the run that I've shown the graph for above was done on a standard 400m athletic track -- at a place where I go regularly for running (Guru Gobind Singh stadium, Jalandhar) -- and Pacer calculated my total distance to be 11.92K while the actual was 12K. Not bad at all; given that the device doesn't use any GPS or anything (and my "run" turned out to be a mixture of brisk walking and running), I am quite impressed with the accuracy of distance measurement.

Running with miCoach

Getting the device setup was not that hard -- although it did take me a bit of time to figure out where the battery for the stride sensor was (hidden in a corner of the packaging, hard to get), and a bit of time figuring out how to take the stride sensor out of the lace clip without damaging either the sensor or the clip. Once that was done, the rest was pretty easy -- strap on the HR monitor onto the chest, clip the Pacer onto shorts (which is most convenient for me), the stride sensor on the shoe, connect headphones to the Pacer and we're ready to go!

One can run the Pacer in "free mode", where it just collects stats for the run, or in "miCoach mode", where you can select a custom workout to work with. There are buttons to pause/resume workout and control the volume. Finally, there's a big button in the center which gives current summary about the run whenever you press it.

All in all, pretty useful except for the fact that I need to have a headphone in my ear all the time (unless I am using it in free mode), which, as I said before, is a bit irritating.

Heart rate zones

As I mentioned earlier, the division of heart rate into zones seems to be one of the more important aspects of miCoach. However, callibrating the zones correctly has been a bit of a challenge for me. I did a 12-minute assessment workout (provided on the website) to callibrate my heart rate zones correctly the first time I took miCoach out for a run. Basically, the workout was like -- run at effort level 5 on a scale of 10, run at level 6 on a scale of 10, etc. I mean, WTF? How much effort you are putting in a run is a difficult thing to quantify. I could probably tell whether I am running easy, hard or very hard. But its a little harder to figure whether I am running at level 6 or 7. Hopefully they will come up with a better assessment workout than this.

So basically, this assessment workout comes up with a completely screwed up callibration of my heart rate zones -- as the graph above for my long run shows. I was struggling really hard to stay in the green zone (which is meant to be an easy run zone); doing a brisk walk meant I was hovering just above the blue zone, while breaking out into an easy run would put me into the yellow zone. Then I decided to just forget it after covering half the distance and do what I really considered to be an easy run. Seems like my average HR for an easy run itself seems to be around 150 beats per min -- so I will adjust the device settings accordingly.

I should get a better idea in the coming weeks about how useful the zones thing really is. Still, I think the device is useful, if for nothing else than to measure distance and pace while running on routes where there's no easy way to judge the distance. And if the HR meter turns out to be accurate, even better.

That's it for now. Next week I'll see if I am able to correctly callibrate the HR zones, and write more about my running experiences with this new toy.

Labels: , ,



This page is powered by Blogger. Isn't yours?

Subscribe to Posts [Atom]