Path: blob/master/src/sage/modules/vector_mod2_dense.pyx
8815 views
"""1Vectors with elements in GF(2).23AUTHOR:45- Martin Albrecht (2009-12): initial implementation67- Thomas Feulner (2012-11): added :meth:`Vector_mod2_dense.hamming_weight`89EXAMPLES::1011sage: VS = GF(2)^312sage: e = VS.random_element(); e13(1, 0, 0)14sage: f = VS.random_element(); f15(0, 1, 1)16sage: e + f17(1, 1, 1)18"""1920##############################################################################21# Copyright (C) 2009 Martin Albrecht <[email protected]>22# Distributed under the terms of the GNU General Public License (GPL)23# The full text of the GPL is available at:24# http://www.gnu.org/licenses/25##############################################################################2627include 'sage/ext/interrupt.pxi'28include 'sage/ext/stdsage.pxi'2930from sage.rings.finite_rings.integer_mod cimport IntegerMod_int, IntegerMod_abstract31from sage.rings.integer cimport Integer32from sage.structure.element cimport Element, ModuleElement, RingElement, Vector3334cimport free_module_element35from free_module_element import vector3637from sage.libs.m4ri cimport *3839cdef class Vector_mod2_dense(free_module_element.FreeModuleElement):40cdef _new_c(self):41"""42EXAMPLE::4344sage: VS = VectorSpace(GF(2),3)45sage: VS([0,0,1])46(0, 0, 1)47sage: type(_)48<type 'sage.modules.vector_mod2_dense.Vector_mod2_dense'>49"""50cdef Vector_mod2_dense y51y = PY_NEW(Vector_mod2_dense)52y._init(self._degree, self._parent)53return y5455cdef bint is_dense_c(self):56"""57EXAMPLE::5859sage: VS = VectorSpace(GF(2),3)60sage: VS([0,0,1]).is_dense()61True62"""63return 16465cdef bint is_sparse_c(self):66"""67EXAMPLE::6869sage: VS = VectorSpace(GF(2),3)70sage: VS([0,0,1]).is_sparse()71False72"""73return 07475def __copy__(self):76"""77EXAMPLE::7879sage: VS = VectorSpace(GF(2),10^4)80sage: v = VS.random_element()81sage: w = copy(v)82sage: w == v83True84sage: v[:10]85(1, 0, 0, 0, 1, 1, 1, 0, 0, 1)86sage: w[:10]87(1, 0, 0, 0, 1, 1, 1, 0, 0, 1)88"""89cdef Vector_mod2_dense y = self._new_c()90if self._degree:91mzd_copy(y._entries, self._entries)92return y9394cdef _init(self, Py_ssize_t degree, parent):95"""96EXAMPLE::9798sage: VS = VectorSpace(GF(2),3)99sage: VS([0,0,1])100(0, 0, 1)101sage: type(_)102<type 'sage.modules.vector_mod2_dense.Vector_mod2_dense'>103"""104self._degree = degree105self._parent = parent106self._base_ring = parent.base_ring()107self._entries = mzd_init(1, degree)108if self._entries == NULL:109raise MemoryError("Allocation of Vector_mod2_dense failed.")110111def __cinit__(self, parent=None, x=None, coerce=True, copy=True):112"""113EXAMPLE::114115sage: VS = VectorSpace(GF(2),3)116sage: VS((0,0,1/3))117(0, 0, 1)118sage: type(_)119<type 'sage.modules.vector_mod2_dense.Vector_mod2_dense'>120"""121self._entries = NULL122self._is_mutable = 1123if not parent is None:124self._init(parent.degree(), parent)125126def __init__(self, parent, x, coerce=True, copy=True):127"""128EXAMPLE::129130sage: VS = VectorSpace(GF(2),3)131sage: VS((0,0,1/3))132(0, 0, 1)133sage: type(_)134<type 'sage.modules.vector_mod2_dense.Vector_mod2_dense'>135sage: VS((0,0,int(3)))136(0, 0, 1)137sage: VS((0,0,3))138(0, 0, 1)139sage: VS((0,0,GF(2)(1)))140(0, 0, 1)141142TESTS:143144Check that ticket #8601 is fixed::145146sage: VS = VectorSpace(GF(2), 3)147sage: VS((-1,-2,-3))148(1, 0, 1)149sage: V = VectorSpace(GF(2), 2)150sage: V([1,3])151(1, 1)152sage: V([1,-3])153(1, 1)154"""155cdef Py_ssize_t i156cdef int xi157if isinstance(x, (list, tuple)):158if len(x) != self._degree:159raise TypeError("x must be a list of the right length")160for i from 0 <= i < self._degree:161if PY_TYPE_CHECK(x[i],IntegerMod_int) or PY_TYPE_CHECK(x[i],int) or PY_TYPE_CHECK(x[i],Integer):162xi = x[i]163# the if/else statement is because in some compilers, (-1)%2 is -1164mzd_write_bit(self._entries, 0, i, 0 if xi%2==0 else 1)165else:166mzd_write_bit(self._entries, 0, i, x[i]%2)167return168if x != 0:169raise TypeError("can't initialize vector from nonzero non-list")170else:171for i from 0 <= i < self._degree:172mzd_set_ui(self._entries, 0)173174def __dealloc__(self):175"""176EXAMPLE::177178sage: VS = VectorSpace(GF(2),10^3)179sage: import gc180sage: for i in range(10):181... v = VS.random_element()182... del v183... _ = gc.collect()184"""185if self._entries:186mzd_free(self._entries)187188cdef int _cmp_c_impl(left, Element right) except -2:189"""190EXAMPLES::191sage: v = vector(GF(2), [0,0,0,0])192sage: v == 0193True194sage: v == 1195False196sage: v == v197True198sage: w = vector(GF(2), [1,0,0,0])199sage: w < v200False201sage: w > v202True203"""204if left._degree == 0:205return 0206return mzd_cmp(left._entries, (<Vector_mod2_dense>right)._entries)207208# see sage/structure/element.pyx209def __richcmp__(left, right, int op):210"""211TEST::212213sage: w = vector(GF(2), [-1,0,0,0])214sage: w == w215True216"""217return (<Element>left)._richcmp(right, op)218219# __hash__ is not properly inherited if comparison is changed220def __hash__(self):221"""222TEST::223224sage: w = vector(GF(2), [-1,0,0,0])225sage: w.set_immutable()226sage: isinstance(hash(w), int)227True228"""229return free_module_element.FreeModuleElement.__hash__(self)230231def __len__(self):232"""233EXAMPLES::234235sage: len(vector(GF(2),[0,0,1,1,1]))2365237"""238return self._degree239240def __setitem__(self, i, value):241"""242EXAMPLES::243244sage: VS = VectorSpace(GF(2),4)245sage: v = VS.random_element(); v246(1, 0, 0, 0)247sage: v[0] = 0; v248(0, 0, 0, 0)249sage: v[1:3] = [1, 1]; v250(0, 1, 1, 0)251sage: v[4] = 0252Traceback (most recent call last):253...254IndexError: Index '4' out of bound.255"""256if not self._is_mutable:257raise ValueError("vector is immutable; please change a copy instead (use copy())")258cdef IntegerMod_int m259cdef Py_ssize_t k, d, n260if isinstance(i, slice):261start, stop = i.start, i.stop262d = self.degree()263R = self.base_ring()264n = 0265for k from start <= k < stop:266if k >= d:267return268if k >= 0:269self[k] = R(value[n])270n = n + 1271else:272m = self.base_ring()(value)273if i < 0 or i >= self._degree:274raise IndexError("Index '%s' out of bound."%(i))275else:276mzd_write_bit(self._entries, 0, i, m)277278def __getitem__(self, i):279"""280Returns `i`-th entry or slice of self.281282EXAMPLES::283284sage: v = vector(GF(2), [1,2,3]); v285(1, 0, 1)286sage: v[0]2871288sage: v[2]2891290sage: v[-2]2910292sage: v[0:2]293(1, 0)294sage: v[5]295Traceback (most recent call last):296...297IndexError: index '5' out of range298299sage: v[-5]300Traceback (most recent call last):301...302IndexError: index '-2' out of range303"""304if isinstance(i, slice):305start, stop, step = i.indices(len(self))306return vector(self.base_ring(), self.list()[start:stop])307else:308if i < 0:309i += self._degree310if i < 0 or i >= self._degree:311raise IndexError("index '%s' out of range"%(i,))312return self._base_ring(mzd_read_bit(self._entries, 0, i))313314def __reduce__(self):315"""316EXAMPLE::317318sage: VS = VectorSpace(GF(2),10^4)319sage: e = VS.random_element()320sage: loads(dumps(e)) == e321True322"""323return unpickle_v0, (self._parent, self.list(), self._degree, self._is_mutable)324325cpdef ModuleElement _add_(self, ModuleElement right):326"""327EXAMPLE::328329sage: VS = VectorSpace(GF(2),10)330sage: e = VS([0,0,1,1,0,0,1,1,0,0])331sage: f = VS([0,1,0,1,0,1,0,1,0,1])332sage: e + f #indirect doctest333(0, 1, 1, 0, 0, 1, 1, 0, 0, 1)334"""335cdef Vector_mod2_dense z = self._new_c()336if self._degree:337mzd_add(z._entries, self._entries, (<Vector_mod2_dense>right)._entries)338return z339340cpdef ModuleElement _sub_(self, ModuleElement right):341"""342EXAMPLE::343344sage: VS = VectorSpace(GF(2),10)345sage: e = VS([0,0,1,1,0,0,1,1,0,0])346sage: f = VS([0,1,0,1,0,1,0,1,0,1])347sage: e - f #indirect doctest348(0, 1, 1, 0, 0, 1, 1, 0, 0, 1)349"""350cdef Vector_mod2_dense z = self._new_c()351if self._degree:352mzd_add(z._entries, self._entries, (<Vector_mod2_dense>right)._entries)353return z354355cpdef int hamming_weight(self):356"""357Return the number of positions ``i`` such that ``self[i] != 0``.358359EXAMPLES::360361sage: vector(GF(2), [1,1,0]).hamming_weight()3622363"""364cdef int i365cdef int res = 0366for i from 0 <= i < self._entries.width:367res += Integer(self._entries.rows[0][i]).popcount()368return res369370371cpdef Element _dot_product_(self, Vector right):372"""373EXAMPLES::374sage: VS = VectorSpace(GF(2),3)375sage: v = VS([1,1,1]); w = VS([0,0,0])376sage: v * w, w * v #indirect doctest377(0, 0)378sage: v = VS([1,1,1]); w = VS([0,1,0])379sage: v * w, w * v380(1, 1)381sage: v = VS([1,1,1]); w = VS([0,1,1])382sage: v * w, w * v383(0, 0)384sage: v = VS([1,1,1]); w = VS([1,1,1])385sage: v * w, w * v386(1, 1)387388sage: VS = VectorSpace(GF(2),10^4)389sage: v = VS(0); w = VS(0)390sage: v[1337] = 1; w[1337] = 1391sage: v * w, w * v392(1, 1)393sage: v[9881] = 1; w[9881] = 1394sage: v * w, w * v395(0, 0)396sage: v[5172] = 1; w[6178] = 1397sage: v * w, w * v398(0, 0)399"""400cdef Py_ssize_t i401cdef IntegerMod_int n402cdef Vector_mod2_dense r = right403cdef m4ri_word tmp = 0404n = IntegerMod_int.__new__(IntegerMod_int)405IntegerMod_abstract.__init__(n, self.base_ring())406n.ivalue = 0407408for i from 0 <= i < self._entries.width:409tmp ^= self._entries.rows[0][i] & r._entries.rows[0][i]410411for i in range(64):412n.ivalue ^= <int>(tmp & 1)413tmp = tmp >> 1414415return n416417cpdef Vector _pairwise_product_(self, Vector right):418"""419EXAMPLE::420421sage: VS = VectorSpace(GF(2),10)422sage: e = VS.random_element(); e423(1, 0, 0, 0, 1, 1, 1, 0, 0, 1)424sage: f = VS.random_element(); f425(1, 1, 0, 1, 1, 1, 0, 0, 0, 1)426sage: e.pairwise_product(f) #indirect doctest427(1, 0, 0, 0, 1, 1, 0, 0, 0, 1)428"""429cdef Vector_mod2_dense z, r430r = right431z = self._new_c()432cdef Py_ssize_t i433for i from 0 <= i < self._entries.width:434z._entries.rows[0][i] = (self._entries.rows[0][i] & r._entries.rows[0][i])435return z436437cpdef ModuleElement _rmul_(self, RingElement left):438"""439EXAMPLE::440441sage: VS = VectorSpace(GF(2),10)442sage: e = VS.random_element(); e443(1, 0, 0, 0, 1, 1, 1, 0, 0, 1)444sage: 0 * e445(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)446sage: 1 * e447(1, 0, 0, 0, 1, 1, 1, 0, 0, 1)448sage: 2 * e #indirect doctest449(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)450"""451cdef IntegerMod_int a452453if left:454return self.__copy__()455else:456return self._new_c()457458459cpdef ModuleElement _lmul_(self, RingElement right):460"""461EXAMPLE::462463sage: VS = VectorSpace(GF(2),10)464sage: e = VS.random_element(); e465(1, 0, 0, 0, 1, 1, 1, 0, 0, 1)466sage: e * 0 #indirect doctest467(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)468sage: e * 1469(1, 0, 0, 0, 1, 1, 1, 0, 0, 1)470sage: e * 2471(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)472"""473return self._rmul_(right)474475cpdef ModuleElement _neg_(self):476"""477EXAMPLE::478479sage: VS = VectorSpace(GF(2),10)480sage: e = VS.random_element()481sage: -e == e482True483"""484return self.__copy__()485486def n(self, *args, **kwargs):487"""488Returns a numerical approximation of ``self`` by calling the489:meth:`n()` method on all of its entries.490491EXAMPLES::492493sage: v = vector(GF(2), [1,2,3])494sage: v.n()495(1.00000000000000, 0.000000000000000, 1.00000000000000)496sage: _.parent()497Vector space of dimension 3 over Real Field with 53 bits of precision498sage: v.n(prec=75)499(1.000000000000000000000, 0.0000000000000000000000, 1.000000000000000000000)500sage: _.parent()501Vector space of dimension 3 over Real Field with 75 bits of precision502"""503return vector( [e.n(*args, **kwargs) for e in self] )504505def list(self, copy=True):506"""507Return a list of entries in ``self``.508509INPUT:510511- ``copy`` - always ``True512513EXAMPLE::514515sage: VS = VectorSpace(GF(2),10)516sage: e = VS.random_element(); e517(1, 0, 0, 0, 1, 1, 1, 0, 0, 1)518sage: e.list()519[1, 0, 0, 0, 1, 1, 1, 0, 0, 1]520"""521cdef Py_ssize_t d = self._degree522cdef Py_ssize_t i523cdef list v = [0]*d524K = self.base_ring()525z = K.zero_element()526o = K.one_element()527cdef list switch = [z,o]528for i in range(d):529v[i] = switch[mzd_read_bit(self._entries, 0, i)]530return v531532def unpickle_v0(parent, entries, degree, is_mutable):533"""534EXAMPLE::535536sage: from sage.modules.vector_mod2_dense import unpickle_v0537sage: VS = VectorSpace(GF(2),10)538sage: unpickle_v0(VS, [0,1,2,3,4,5,6,7,8,9], 10, 0)539(0, 1, 0, 1, 0, 1, 0, 1, 0, 1)540"""541# If you think you want to change this function, don't.542cdef Vector_mod2_dense v543v = PY_NEW(Vector_mod2_dense)544v._init(degree, parent)545cdef int xi546547for i from 0 <= i < degree:548if PY_TYPE_CHECK(entries[i],IntegerMod_int) or PY_TYPE_CHECK(entries[i],int) or PY_TYPE_CHECK(entries[i],Integer):549xi = entries[i]550mzd_write_bit(v._entries, 0, i, xi%2)551else:552mzd_write_bit(v._entries, 0, i, entries[i]%2)553v._is_mutable = int(is_mutable)554return v555556557558