Ticket #8379: trac_8379.patch

File trac_8379.patch, 9.7 KB (added by ylchapuy, 3 years ago)
  • sage/crypto/boolean_function.pyx

    # HG changeset patch
    # User Yann Laigle-Chapuy <yannlaiglechapuy@gmail.com>
    # Date 1267190219 -7200
    # Node ID 6d1ac120fc3be26317b257463a0c44ac8af81cf3
    # Parent  46b1ee5997ac7e7faafdd86751fe7d121b6c1385
    add arithmetic to boolean_function
    
    diff -r 46b1ee5997ac -r 6d1ac120fc3b sage/crypto/boolean_function.pyx
    a b  
    77This module allows to study properties linked to spectral analysis, 
    88and also algebraic immunity. 
    99 
    10 EXAMPLE:: 
     10EXAMPLES:: 
    1111 
    1212    sage: R.<x>=GF(2^8,'a')[] 
    1313    sage: from sage.crypto.boolean_function import BooleanFunction 
     
    2121 
    2222AUTHOR: 
    2323 
     24- Yann Laigle-Chapuy (2010-02-26): add basic arithmetic 
    2425- Yann Laigle-Chapuy (2009-08-28): first implementation 
    2526 
    2627""" 
     
    327328                else: 
    328329                    for i,u in enumerate(K): 
    329330                        bitset_set_to(self._truth_table, i , (x(u)).trace()) 
    330  
     331        elif isinstance(x, BooleanFunction): 
     332            self._nvariables = x.nvariables() 
     333            bitset_init(self._truth_table,(1<<self._nvariables)) 
     334            bitset_copy(self._truth_table,(<BooleanFunction>x)._truth_table) 
    331335        else: 
    332336            raise TypeError, "unable to init the Boolean function" 
    333337 
     
    347351            r += "s" 
    348352        return r 
    349353 
     354    def __invert__(self): 
     355        """ 
     356        Return the complement Boolean function of `self`. 
     357 
     358        EXAMPLE:: 
     359 
     360            sage: from sage.crypto.boolean_function import BooleanFunction 
     361            sage: B=BooleanFunction([0, 1, 1, 0, 1, 0, 0, 0]) 
     362            sage: (~B).truth_table(format='int') 
     363            (1, 0, 0, 1, 0, 1, 1, 1) 
     364        """ 
     365        cdef BooleanFunction res=BooleanFunction(self.nvariables()) 
     366        bitset_complement(res._truth_table, self._truth_table) 
     367        return res 
     368         
     369    def __iadd__(self, BooleanFunction other): 
     370        """ 
     371        Inplace add `other` to `self`. 
     372 
     373        EXAMPLE:: 
     374         
     375            sage: from sage.crypto.boolean_function import BooleanFunction 
     376            sage: A=BooleanFunction([0, 1, 0, 1, 1, 0, 0, 1]) 
     377            sage: A += BooleanFunction([0, 1, 1, 0, 1, 0, 0, 0]) 
     378            sage: A.truth_table(format='int') 
     379            (0, 0, 1, 1, 0, 0, 0, 1)         
     380 
     381        TESTS:: 
     382 
     383            sage: A+=BooleanFunction([0,1]) 
     384            Traceback (most recent call last): 
     385            ... 
     386            ValueError: the two Boolean functions must have the same number of variables 
     387        """ 
     388        if (self._nvariables != other._nvariables): 
     389            raise ValueError("the two Boolean functions must have the same number of variables") 
     390        bitset_xor(self._truth_table, self._truth_table, other._truth_table) 
     391        return self 
     392         
     393    def __add__(self, other): 
     394        """ 
     395        Return the element wise sum of `self`and `other` which must have the same number of variables. 
     396 
     397        EXAMPLE:: 
     398         
     399            sage: from sage.crypto.boolean_function import BooleanFunction 
     400            sage: A=BooleanFunction([0, 1, 0, 1, 1, 0, 0, 1]) 
     401            sage: B=BooleanFunction([0, 1, 1, 0, 1, 0, 0, 0]) 
     402            sage: (A+B).truth_table(format='int') 
     403            (0, 0, 1, 1, 0, 0, 0, 1) 
     404 
     405        it also corresponds to the addition of algebraic normal forms:: 
     406 
     407            sage: S = A.algebraic_normal_form() + B.algebraic_normal_form() 
     408            sage: (A+B).algebraic_normal_form() == S 
     409            True 
     410 
     411        TESTS:: 
     412 
     413            sage: A+BooleanFunction([0,1]) 
     414            Traceback (most recent call last): 
     415            ... 
     416            ValueError: the two Boolean functions must have the same number of variables 
     417        """ 
     418        cdef BooleanFunction res=BooleanFunction(self) 
     419        res += other 
     420        return res 
     421         
     422    def __imul__(self, BooleanFunction other): 
     423        """ 
     424        Inplace multiply `other` to `self`. 
     425 
     426        EXAMPLE:: 
     427         
     428            sage: from sage.crypto.boolean_function import BooleanFunction 
     429            sage: A=BooleanFunction([0, 1, 0, 1, 1, 0, 0, 1]) 
     430            sage: A += BooleanFunction([0, 1, 1, 0, 1, 0, 0, 0]) 
     431            sage: A.truth_table(format='int') 
     432            (0, 0, 1, 1, 0, 0, 0, 1) 
     433 
     434        TESTS:: 
     435 
     436            sage: A*=BooleanFunction([0,1]) 
     437            Traceback (most recent call last): 
     438            ... 
     439            ValueError: the two Boolean functions must have the same number of variables 
     440        """ 
     441        if (self._nvariables != other._nvariables): 
     442            raise ValueError("the two Boolean functions must have the same number of variables") 
     443        bitset_and(self._truth_table, self._truth_table, other._truth_table) 
     444        return self 
     445 
     446    def __mul__(self, other): 
     447        """ 
     448        Return the elementwise multiplication of `self`and `other` which must have the same number of variables. 
     449 
     450        EXAMPLE:: 
     451         
     452            sage: from sage.crypto.boolean_function import BooleanFunction 
     453            sage: A=BooleanFunction([0, 1, 0, 1, 1, 0, 0, 1]) 
     454            sage: B=BooleanFunction([0, 1, 1, 0, 1, 0, 0, 0]) 
     455            sage: (A*B).truth_table(format='int') 
     456            (0, 1, 0, 0, 1, 0, 0, 0) 
     457 
     458        it also corresponds to the multiplication of algebraic normal forms:: 
     459 
     460            sage: P = A.algebraic_normal_form() * B.algebraic_normal_form() 
     461            sage: (A*B).algebraic_normal_form() == P 
     462            True 
     463 
     464        TESTS:: 
     465 
     466            sage: A*BooleanFunction([0,1]) 
     467            Traceback (most recent call last): 
     468            ... 
     469            ValueError: the two Boolean functions must have the same number of variables 
     470        """ 
     471        cdef BooleanFunction res=BooleanFunction(self) 
     472        res *= other 
     473        return res 
     474 
     475    def __or__(BooleanFunction self, BooleanFunction other): 
     476        """ 
     477        Return the concatenation of `self` and `other` which must have the same number of variables. 
     478 
     479        EXAMPLE:: 
     480 
     481            sage: from sage.crypto.boolean_function import BooleanFunction 
     482            sage: A=BooleanFunction([0, 1, 0, 1]) 
     483            sage: B=BooleanFunction([0, 1, 1, 0]) 
     484            sage: (A|B).truth_table(format='int') 
     485            (0, 1, 0, 1, 0, 1, 1, 0) 
     486 
     487            sage: C = A.truth_table() + B.truth_table() 
     488            sage: (A|B).truth_table(format='int') == C 
     489            True 
     490 
     491        TESTS:: 
     492 
     493            sage: A|BooleanFunction([0,1]) 
     494            Traceback (most recent call last): 
     495            ... 
     496            ValueError: the two Boolean functions must have the same number of variables 
     497        """ 
     498        if (self._nvariables != other.nvariables()): 
     499            raise ValueError("the two Boolean functions must have the same number of variables") 
     500 
     501        cdef BooleanFunction res=BooleanFunction(self.nvariables()+1) 
     502 
     503        nb_limbs = self._truth_table.limbs 
     504        if nb_limbs == 1: 
     505            L = len(self) 
     506            for i in range(L): 
     507                res[i  ]=self[i] 
     508                res[i+L]=other[i] 
     509            return res 
     510 
     511        memcpy(res._truth_table.bits             , self._truth_table.bits, nb_limbs * sizeof(unsigned long)) 
     512        memcpy(&(res._truth_table.bits[nb_limbs]),other._truth_table.bits, nb_limbs * sizeof(unsigned long)) 
     513 
     514        return res 
     515         
     516 
    350517    def algebraic_normal_form(self): 
    351518        """ 
    352519        Return the :class:`sage.rings.polynomial.pbori.BooleanPolynomial` 
     
    403570        INPUT: a string representing the desired format, can be either 
    404571 
    405572        - 'bin' (default) : we return a tuple of Boolean values 
     573        - 'int' : we return a tuple of 0 or 1 values 
    406574        - 'hex' : we return a string representing the truth_table in hexadecimal 
    407575 
    408576        EXAMPLE:: 
     
    412580            sage: B = BooleanFunction( x*y*z + z + y + 1 ) 
    413581            sage: B.truth_table() 
    414582            (True, True, False, False, False, False, True, False) 
     583            sage: B.truth_table(format='int') 
     584            (1, 1, 0, 0, 0, 0, 1, 0) 
    415585            sage: B.truth_table(format='hex') 
    416586            '43' 
    417587 
     
    425595        """ 
    426596        if format is 'bin': 
    427597            return tuple(self) 
     598        if format is 'int': 
     599            return tuple(map(int,self)) 
    428600        if format is 'hex': 
    429601            S = "" 
    430602            S = ZZ(self.truth_table(),2).str(16) 
     
    8321004    def algebraic_immunity(self, annihilator = False): 
    8331005        """ 
    8341006        Returns the algebraic immunity of the Boolean function. This is the smallest 
    835         integer `i` such that there exists a non trivial annihilator. 
     1007        integer `i` such that there exists a non trivial annihilator for `self` or `~self`. 
    8361008         
    8371009        INPUT: 
    8381010         
     
    8471019            (2, x0*x1 + x1*x2 + x2*x3 + x3*x4 + x4*x5 + 1) 
    8481020            sage: B[0] +=1 
    8491021            sage: B.algebraic_immunity() 
    850             3 
     1022            2 
    8511023 
    8521024            sage: R.<x> = GF(2^8,'a')[] 
    8531025            sage: B = BooleanFunction(x^31) 
    8541026            sage: B.algebraic_immunity() 
    8551027            4 
    8561028        """ 
     1029        f = self 
     1030        g = ~self 
    8571031        for i in xrange(self._nvariables): 
    858             A = self.annihilator(i) 
    859             if A is not None: 
    860                 if annihilator: 
    861                     return i,A 
    862                 else: 
    863                     return i 
     1032            for fun in [f,g]: 
     1033                A = fun.annihilator(i) 
     1034                if A is not None: 
     1035                    if annihilator: 
     1036                        return i,A 
     1037                    else: 
     1038                        return i 
    8641039        raise ValueError, "you just found a bug!"         
    8651040                 
    8661041    def __setitem__(self, i, y): 
     
    8961071            sage: B=BooleanFunction([0,1,1,1]) 
    8971072            sage: [ int(B[i]) for i in range(len(B)) ] 
    8981073            [0, 1, 1, 1] 
    899              
    9001074        """ 
    9011075        return self.__call__(i) 
    9021076