Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
using int_fast64 for vector_modn_sparse
Browse files Browse the repository at this point in the history
  • Loading branch information
fchapoton committed Sep 25, 2019
1 parent 2ab843c commit bc31936
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 38 deletions.
14 changes: 8 additions & 6 deletions src/sage/modules/vector_modn_sparse.pxd
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from sage.rings.finite_rings.stdint cimport *

cdef struct c_vector_modint:
int *entries
int_fast64_t *entries
int p
Py_ssize_t *positions
Py_ssize_t degree
Expand All @@ -8,10 +10,10 @@ cdef struct c_vector_modint:
cdef int allocate_c_vector_modint(c_vector_modint* v, Py_ssize_t num_nonzero) except -1
cdef int init_c_vector_modint(c_vector_modint* v, int p, Py_ssize_t degree, Py_ssize_t num_nonzero) except -1
cdef void clear_c_vector_modint(c_vector_modint* v)
cdef Py_ssize_t binary_search0_modn(Py_ssize_t* v, Py_ssize_t n, int x)
cdef Py_ssize_t binary_search_modn(Py_ssize_t* v, Py_ssize_t n, int x, Py_ssize_t* ins)
cdef int get_entry(c_vector_modint* v, Py_ssize_t n) except -1
cdef Py_ssize_t binary_search0_modn(Py_ssize_t* v, Py_ssize_t n, int_fast64_t x)
cdef Py_ssize_t binary_search_modn(Py_ssize_t* v, Py_ssize_t n, int_fast64_t x, Py_ssize_t* ins)
cdef int_fast64_t get_entry(c_vector_modint* v, Py_ssize_t n) except -1
cdef object to_list(c_vector_modint* v)
cdef int set_entry(c_vector_modint* v, Py_ssize_t n, int x) except -1
cdef int set_entry(c_vector_modint* v, Py_ssize_t n, int_fast64_t x) except -1
cdef int add_c_vector_modint_init(c_vector_modint* sum, c_vector_modint* v, c_vector_modint* w, int multiple) except -1
cdef int scale_c_vector_modint(c_vector_modint* v, int scalar) except -1
cdef int scale_c_vector_modint(c_vector_modint* v, int_fast64_t scalar) except -1
74 changes: 42 additions & 32 deletions src/sage/modules/vector_modn_sparse.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,62 @@
# Copyright (C) 2004, 2007 William Stein <[email protected]>
# Distributed under the terms of the GNU General Public License (GPL)
# The full text of the GPL is available at:
# http://www.gnu.org/licenses/
# https://www.gnu.org/licenses/
#############################################################################

from cysignals.memory cimport sig_malloc, sig_free

from sage.modules.vector_modn_sparse cimport c_vector_modint


cdef int allocate_c_vector_modint(c_vector_modint* v, Py_ssize_t num_nonzero) except -1:
"""
Allocate memory for a c_vector_modint -- most user code won't call this.
"""
v.entries = <int*>sig_malloc(num_nonzero*sizeof(int))
v.entries = <int_fast64_t*>sig_malloc(num_nonzero*sizeof(int_fast64_t))
if v.entries == NULL:
raise MemoryError("Error allocating memory")
raise MemoryError("error allocating memory")
v.positions = <Py_ssize_t*>sig_malloc(num_nonzero*sizeof(Py_ssize_t))
if v.positions == NULL:
sig_free(v.entries)
raise MemoryError("Error allocating memory")
raise MemoryError("error allocating memory")
return 0


cdef int init_c_vector_modint(c_vector_modint* v, int p, Py_ssize_t degree,
Py_ssize_t num_nonzero) except -1:
"""
Initialize a c_vector_modint.
"""
if (allocate_c_vector_modint(v, num_nonzero) == -1):
raise MemoryError("Error allocating memory for sparse vector.")
raise MemoryError("error allocating memory for sparse vector")
if p > 46340:
clear_c_vector_modint(v)
raise OverflowError("The prime must be <= 46340.")
raise OverflowError("the prime must be <= 46340")
v.num_nonzero = num_nonzero
v.degree = degree
v.p = p
return 0


cdef void clear_c_vector_modint(c_vector_modint* v):
sig_free(v.entries)
sig_free(v.positions)

cdef Py_ssize_t binary_search0_modn(Py_ssize_t* v, Py_ssize_t n, int x):

cdef Py_ssize_t binary_search0_modn(Py_ssize_t* v, Py_ssize_t n, int_fast64_t x):
"""
Find the position of the int x in the array v, which has length n.
Returns -1 if x is not in the array v.
Return -1 if x is not in the array v.
"""
if n == 0:
return -1

cdef Py_ssize_t i, j, k
i = 0
j = n-1
while i<=j:
while i <= j:
if i == j:
if v[i] == x:
return i
Expand All @@ -66,10 +71,12 @@ cdef Py_ssize_t binary_search0_modn(Py_ssize_t* v, Py_ssize_t n, int x):
return k
return -1

cdef Py_ssize_t binary_search_modn(Py_ssize_t* v, Py_ssize_t n, int x, Py_ssize_t* ins):

cdef Py_ssize_t binary_search_modn(Py_ssize_t* v, Py_ssize_t n, int_fast64_t x, Py_ssize_t* ins):
"""
Find the position of the integer x in the array v, which has length n.
Returns -1 if x is not in the array v, and in this case ins is
Return -1 if x is not in the array v, and in this case ins is
set equal to the position where x should be inserted in order to
obtain an ordered array.
"""
Expand All @@ -80,7 +87,7 @@ cdef Py_ssize_t binary_search_modn(Py_ssize_t* v, Py_ssize_t n, int x, Py_ssize_
cdef Py_ssize_t i, j, k
i = 0
j = n-1
while i<=j:
while i <= j:
if i == j:
if v[i] == x:
ins[0] = i
Expand All @@ -98,49 +105,54 @@ cdef Py_ssize_t binary_search_modn(Py_ssize_t* v, Py_ssize_t n, int x, Py_ssize_
else: # only possibility is that v[k] == x
ins[0] = k
return k
# end while
ins[0] = j+1
return -1

cdef int get_entry(c_vector_modint* v, Py_ssize_t n) except -1:

cdef int_fast64_t get_entry(c_vector_modint* v, Py_ssize_t n) except -1:
"""
Returns the n-th entry of the sparse vector v. This
would be v[n] in Python syntax.
Return the n-th entry of the sparse vector v.
This would be v[n] in Python syntax.
"""
if n >= v.degree or n < 0:
raise IndexError("Index must be between 0 and the degree minus 1.")
raise IndexError("index must be between 0 and the degree minus 1")
cdef Py_ssize_t m
m = binary_search0_modn(v.positions, v.num_nonzero, n)
if m == -1:
return 0
return v.entries[m]


cdef object to_list(c_vector_modint* v):
"""
Returns a Python list of 2-tuples (i,x), where x=v[i] runs
Return a Python list of 2-tuples (i,x), where x=v[i] runs
through the nonzero elements of x, in order.
"""
cdef object X
cdef Py_ssize_t i
X = []
for i from 0 <= i < v.num_nonzero:
X.append( (v.positions[i], v.entries[i]) )
for i in range(v.num_nonzero):
X.append((v.positions[i], v.entries[i]))
return X

cdef int set_entry(c_vector_modint* v, Py_ssize_t n, int x) except -1:

cdef int set_entry(c_vector_modint* v, Py_ssize_t n, int_fast64_t x) except -1:
"""
Set the n-th component of the sparse vector v equal to x.
This would be v[n] = x in Python syntax.
"""
if n < 0 or n >= v.degree:
raise IndexError("Index (=%s) must be between 0 and %s."%(n, v.degree-1))
raise IndexError("index (=%s) must be between 0 and %s" % (n, v.degree-1))
cdef Py_ssize_t i, m, ins
cdef Py_ssize_t m2, ins2
cdef Py_ssize_t *pos
cdef int *e
cdef int_fast64_t *e

x = x % v.p
if x<0: x = x + v.p
if x < 0:
x = x + v.p
m = binary_search_modn(v.positions, v.num_nonzero, n, &ins)

if m != -1:
Expand Down Expand Up @@ -191,15 +203,16 @@ cdef int set_entry(c_vector_modint* v, Py_ssize_t n, int x) except -1:
sig_free(e)
sig_free(pos)


cdef int add_c_vector_modint_init(c_vector_modint* sum, c_vector_modint* v,
c_vector_modint* w, int multiple) except -1:
"""
Set sum = v + multiple*w.
"""
if v.p != w.p:
raise ArithmeticError("The vectors must be modulo the same prime.")
raise ArithmeticError("the vectors must be modulo the same prime")
if v.degree != w.degree:
raise ArithmeticError("The vectors must have the same degree.")
raise ArithmeticError("the vectors must have the same degree")

cdef int s
cdef Py_ssize_t nz, i, j, k
Expand Down Expand Up @@ -260,12 +273,11 @@ cdef int add_c_vector_modint_init(c_vector_modint* sum, c_vector_modint* v,
k = k + 1 # only increment if sum is nonzero!
i = i + 1
j = j + 1
#end if
# end while
z.num_nonzero = k
return 0

cdef int scale_c_vector_modint(c_vector_modint* v, int scalar) except -1:

cdef int scale_c_vector_modint(c_vector_modint* v, int_fast64_t scalar) except -1:
scalar = scalar % v.p
if scalar == 0:
clear_c_vector_modint(v)
Expand All @@ -274,8 +286,6 @@ cdef int scale_c_vector_modint(c_vector_modint* v, int scalar) except -1:
if scalar < 0:
scalar = scalar + v.p
cdef Py_ssize_t i
for i from 0 <= i < v.num_nonzero:
for i in range(v.num_nonzero):
v.entries[i] = (v.entries[i] * scalar) % v.p
return 0


0 comments on commit bc31936

Please sign in to comment.