#!/usr/bin/python
#
# A variant of cyclotomic.py which uses try/except to look for
# dictionary keys.
#
# A word of advice from Fredrik Lundh <Fredrik_Lundh@ivab.se>:
#
#  Python keeps a reference to the last traceback object in
#  sys.exc_traceback, which in turn includes references to items on the
#  run-time stack, etc.  This means that things won't be destroyed until
#  the *next* exception occurs.
#
# Thus, we must clear sys.exc_traceback before calling MnAllocStats()
# if we want the real statistics.

from saml1 import *
import sys

class CyclotomicClass:

  def __init__(self, literal):
    self.dict = {}
    self.X = literal

  def __getitem__(self, number):
    try:
      # Already computed?
      return self.dict[number]
    except: pass

    result = self.X.pow(number) - 1
    for i in range(1,number):
      if (number % i) == 0:
        result = result / self[i]

    # Memoize the result
    self.dict[number] = result
    return result

def test(n):
  model = Mathnode(ST_INTEGER,'0').cast(ST_APOLY)
  X = model.parse('X')
  CCX = CyclotomicClass(X)
  print CCX[n]

if __name__ == '__main__':
  test(60)
  sys.exc_traceback = None
  print MnAllocStats()
