#-*- coding:utf-8 -*-
import string
from numpy import *

def conversion(nombre, base, epsilon = 0.00001 ):
    ''' Soit nombre écrit en base 10, le retourne en base base'''
    if not 2 <= base <= 36:
        raise ValueError, "La base doit être entre 2 et 36"
    if not base == 2 and '.' in str(nombre):
        raise ValueError, "La partie décimale n'est pas gérée pour les bases\
                           différentes de 2."
    # IMPROVE : Convertir aussi la partie décimale, quand la base n'est pas égale
    # à 2.
    abc = string.digits + string.letters
    result = ''
    if '-' in nombre:
        nombre = nombre.replace('-','')
        sign = '-'
    else:
        sign = ''
    if '.' in str(nombre):
        entier,decimal = int(str(nombre).split('.')[0]),\
                         float('.'+str(nombre).split('.')[1])
    else:
        entier,decimal = int(str(nombre)),0
    while entier !=0 :
        entier, rdigit = divmod( entier, base )
        result = abc[rdigit] + result
    flotante, decimalBin = 1./float(base),''
    while flotante > epsilon :
        if decimal >= flotante:
            decimalBin+='1'
            decimal-=flotante
        else :
            decimalBin+='0'    
        flotante = flotante/float(base)
    if '1' in decimalBin :
        reste = '.'+decimalBin
        while reste[-1]=='0':
            reste = reste[:-1]
    else :
        reste = ''
    if result == '':
        result = '0'
    return sign + result + reste

    
def getBit(X,pos):
    '''Récupère le bit en position pos de X.
    Par exemple, getBit(8,1) = 0, puisque le bit le plus à droite de 8 = 1000 est 0.
    On fera attention à ce que :
        - on compte à partir du point,
        - l'élément juste à gauche du point est en position 1,
        - celui juste à droite est en position -1.'''
    assert pos != 0
    entier = conversion(X,2)
    if '.' in entier:
        entier, decimal = entier.split('.')  
        if decimal == '0':
            decimal = ''  
    else:
        decimal = ''
    if '-' in entier:
        entier = entier.replace('-','')
    entier  = entier.zfill(abs(pos))
    decimal = (decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))]

    return int(entier[len(entier)-pos]) if pos >0 else int(decimal[-pos-1])


def setBit(X,pos,y):
    '''Fixe le bit pos de X à la valeur y.
    Le fonctionnement est similaire à getBit : 
        - on compte à partir du point,
        - l'élément juste à gauche du point est en position 1,
        - celui juste à droite est en position -1.'''
    assert pos != 0
    entier = conversion(X,2)
    if '.' in entier:
        entier, decimal = entier.split('.')    
    else:
        decimal = ''
    entier  = list(entier.zfill(abs(pos)))
    decimal = list((decimal+'0'*abs(pos))[:max(len(decimal),abs(pos))])
    if pos>0:
        entier[len(entier)-pos]=str(int(y))
    else:
        decimal[-pos-1] = str(int(y))
    if decimal == []:
        return int(''.join(entier),2)
    else:
        S=0
        for k in range(len(decimal)):
            S += 1./2**(k+1)*int(decimal[k])
        return float(str(int(''.join(entier),2))+'.'+str(S).split('.')[1])


