I'm in the future. Like hundreds of years in the future. I've been dead for centuries.
Oh, lovely, you're a cheery one aren't you?

Friday, February 26


Move Over Mendeleev

Now with added mouseoverness.

Posted by: Pixy Misa at 02:00 AM | Comments (5) | Add Comment | Trackbacks (Suck)
Post contains 7 words, total size 2 kb.

Thursday, February 25



The Periodic Table of Minx
The Grand Unified Minx Theory

The mee.nu Group
The mee.nu User Domains

The Minx Components
The Minx Components

Posted by: Pixy Misa at 05:40 PM | No Comments | Add Comment | Trackbacks (Suck)
Post contains 13 words, total size 1 kb.

Wednesday, February 24


Gamma Lama

Naturally I had to try this...




Now, that's a deliberately constructed corner case, but there is a problem there.

Posted by: Pixy Misa at 12:40 PM | No Comments | Add Comment | Trackbacks (Suck)
Post contains 24 words, total size 1 kb.

Monday, February 22



Posted by: Pixy Misa at 05:44 PM | No Comments | Add Comment | Trackbacks (Suck)
Post contains 2 words, total size 1 kb.

Sunday, February 21


Where's Pixy?

I'm in here:

(Click for full screenshot.  Thanks go to Steam and GOG's insane holiday sales.)

Actually, I'm not; I'm doing work for my day job, making some progress with Pita, reorganising Meta, and have finally come to a design decision on Miko (all parts of the Minx project for those who haven't been paying attention), redoing the documentation in Sphinx - which will itself be supported in an upcoming version of Meta - and planning for this year's server upgrade.*  I did play a bit of Dragon Age over the holidays, but games are taking a back seat for a while.**  Despite the fact that I have 224 of them currently installed.

* If things go right we'll be moving from a lowly 8-processor (16-thread) 2.26GHz server with 24GB of RAM to a spiffy new 12-processor (24-thread) 2.66GHz server with 48GB of RAM.  That's at least partly to prepare for the move to Pita, which loves to store stuff in memory.  Because I can just copy the OpenVZ virtual machines across, the move should be quick and painless.

** Apart from Billy vs. SNAKEMAN!


Posted by: Pixy Misa at 02:16 PM | Comments (6) | Add Comment | Trackbacks (Suck)
Post contains 188 words, total size 1 kb.

Saturday, February 20


If I Don't Lesnerize, The Feegs Can't Get Me

In SQL* you say select sum(sales) from accounts where state="NY".  In Pita, the way to do this is:
results = accounts.aggregate(state='NY')**
which will calculate for you the count, length, sum, minimum and maximum, as appropriate, for all the fields in the table at once, so the value you need is results.sales.sum.  Since the table scan is typically slower than any calculations you're likely to be doing, this seems a reasonable approach.

In addition, I've added a
results = accounts.stats()
which provides all those, plus mean,*** median, mode, standard deviation, and geometric and harmonic means.   Aaaaand standard error, coefficient of variation, sample and population variance, skewness and kurtosis.  I even sort of know what kurtosis is.

I'm working on two more functions now, group and break, though I may need to come up with another name for the latter because break is a Python keyword.  This:
for result in accounts.group('state', country='US'): ...
would give you the aggregate sales figures for each state in the US, sensibly enough.  And this:
for result in accounts.break('state', country='US'): ...
would give you the individual sales figures, and then automatically provide totals after the last sales record for each state.

As long as I don't come down with kurtosis...

Update: Kang and jag.  Or rather, agg and tab.  For aggregate and tabulate. 
for line in accounts.aggregate('state', country='US'): ...
will give you one summary line for each state, where
for line in accounts.tabulate('state', country='US'): ...
would give you both detail and summary lines.  I need to put subtotal and total flags on the records for tabulate.  Have to watch the keywords, there.  And keep my closet doors closed.

* Boo, hiss!

** Or indeed
results = accounts(state='NY').aggregate()
Either way should perform the same and produce the same results.  I think...

*** Which should come out the same as the average; just one I'm calculating myself and the other I'm pulling out of a stats module.

Posted by: Pixy Misa at 03:14 AM | Comments (2) | Add Comment | Trackbacks (Suck)
Post contains 316 words, total size 3 kb.

Tuesday, February 16


Just Trying Something...


Okay, yeah, they needed that sharpening filter.  That's Minx's built-in upscaling.  Quality is not so hot, as it turns out.  I'll check on what filter it's using; normally it's only used for downscaling, which works great:


Posted by: Pixy Misa at 11:35 AM | No Comments | Add Comment | Trackbacks (Suck)
Post contains 39 words, total size 1 kb.

Sunday, February 14


Oodles Of Noodles

I have a working base storage class for Pita.  Unfortunately, most of my weekend was eaten up by my day job and other miscellanea, but it does work.

I'll post the full code later in the week once I have a derived class or two that does something more useful, in the meantime, here's the test code to give you an example of how it's used:
def oodle_test():
  # Create a base view
  pets = Oodle()
  # Create some pets
  log('Creating pets')
  # Create a dog, and save it
  pet = pets.new()
  pet.animal = 'dog'
  pet.sound = 'woof'
  log('Dog saved, %s pets' % pets.count(),1)
  # Create a cat from a dict, and save it
  pet = pets.new({'animal': 'cat', 'sound': 'meow'})
  log('Cat saved, %s pets' % pets.count(),1)
  # Append an aardvark
  pet = pets.append({'animal': 'aardvark', 'sound': 'snorf'})
  log('Aardvark appended, %s pets' % pets.count(),1)
  # Append a hippopotamus too
  pet = pets.append(animal = 'hippopotamus', sound = 'hrooonk')
  log('Hippopotamus appended, %s pets' % pets.count(),1)
  # What pets do I have?
  log('Selecting all pets')
  for pet in pets.select():
    log('My %s says %s' % (pet.animal, pet.sound),1)
  # Select and find on fields
  log('Selecting specific pets')
  # What does my dog say?
  for pet in pets.select(animal = 'dog'):
    log('Selected my %s; it says %s' % (pet.animal, pet.sound),1)
  # Can I find my cat?
  pet = pets.find(animal = 'cat')
  log('Found my %s; it says %s' % (pet.animal, pet.sound),1)
  return pets.count() == 4
The base view class, which has no indexes, no persistence, and no support for sorting, is called an Oodle.

The results of the test?
Creating pets
  Dog saved, 1 pets
  Cat saved, 2 pets
  Aardvark appended, 3 pets
  Hippopotamus appended, 4 pets
Selecting all pets
  My dog says woof
  My cat says meow
  My aardvark says snorf
  My hippopotamus says hrooonk
Selecting specific pets
  Selected my dog; it says woof
  Found my cat; it says meow
Oodle OK
Update: We've hit version 0.02 wih a successful hash-table implementation.  Next up is persistence...  And deletes.

Update: 0.03!  I deleted my pet hippopotamus!

Update: 0.04!  The idiom for pet in pets now works.  You can't slice it or select within it yet.

Posted by: Pixy Misa at 11:34 PM | Comments (8) | Add Comment | Trackbacks (Suck)
Post contains 356 words, total size 3 kb.


Pixy, the Language

Well, sort of.  Kind of sort of.*

Okay, quick, tell me what language this is (without Googling the source code):
print "Eratosthenes' Sieve, in some funny language"

function print_sieve (limit):
  local sieve, j = { }, 2
  while j<limit:
    while sieve[j]:
    for k = j*j, limit, j:
      sieve[k] = true

Hint: That's not it.  And I don't understand the first line of print_sieve at all.  Oh, right.  Logically, (sieve, j) = ({}, 2), so the local variables sieve and j are initialised as an empty dict and 2, respectively.

Hint the second: It's the same language as this (believe it or not):
map    = |f,x| x ? %{ hd=f(x.hd), tl=map(f,x.tl) }
filter = |p,x| x ? p(x.hd) ? %{ hd=x.hd, tl=filter(p, x.tl) }, filter(p, x.tl)
take   = |n,s| n<=0 ? { }, { s.hd, unpack(take(n-1, s.tl)) }
ints   = %{ hd=1; tl=map (|x| x+1, ints) }

f = |seq| %{ hd=seq.hd; tl=f(filter (|x| x%seq.hd~=0, seq.tl)) }
primes = f (ints.tl)

table.print(take (100, primes))
Which implements the exact same function.

Hint the third: You'll be able to script your mee.nu blog like this soon.

* Good language designers borrow.  Great language designers swipe someone else's metaprogramming project.

Posted by: Pixy Misa at 01:48 AM | No Comments | Add Comment | Trackbacks (Suck)
Post contains 199 words, total size 2 kb.

Saturday, February 13


Rhymes With Camel

I was looking at YAML as a serialisation option for Pita (it's already supported for exporting data in the development version of Minx).

So I ran some benchmarks.

It's sloooooooooooooooooooow.

Here we are, encoding and decoding a 2k record:

[andrew@eineus ~]$ python jsonbench.py
10000 iterations on 1973 bytes
json: 10000 encodes+decodes in 4.9 seconds, 2055.8 per second
simplejson: 10000 encodes+decodes in 0.5 seconds, 20686.2 per second
pickle: 10000 encodes+decodes in 4.3 seconds, 2338.0 per second
cPickle: 10000 encodes+decodes in 0.6 seconds, 17297.6 per second
yaml: 10000 encodes+decodes in 213.4 seconds, 46.9 per second

json is Python's built-in JSON library, which is written in Python and thus somewhat sluggish.  simplejson is the same JSON library with an optional C implementation.  Essentially the same applies for pickle vs. cPickle.

yaml is PyYAML, which includes a C implemenation if you have LibYAML installed.  Which I do, but I can't seem to get the C implemenation to run...  Unless that's it, which would be pretty sad.

On the one hand, simplejson is the fastest of these options, which is good because it's also the most widely supported format and the easiest to parse.

One the other hand, 20,000 records per second is not all that much.

Posted by: Pixy Misa at 04:37 PM | Comments (2) | Add Comment | Trackbacks (Suck)
Post contains 205 words, total size 1 kb.

<< Page 1 of 3 >>
77kb generated in CPU 0.0313, elapsed 0.4078 seconds.
55 queries taking 0.3887 seconds, 371 records returned.
Powered by Minx 1.1.6c-pink.
Using https / https://ai.mee.nu / 369