예제 #1
0
def _calcMatrixTrans(calc, tS, tT, lS, lT):
	"""
	See `calcMatrixTrans()` for the main documentation.
	This is the lower-level function which is wrapped through `persistent_cache`.
	This makes the cache more flexible about different parameters
	`R` to `calcMatrixTrans()`.
	"""

	try:
		ms = calc.calcMatrixTrans(tS, tT, lS, lT)
	except Exception:
		print (calc.params, calc.curlS, tS, tT, lS, lT)
		raise

	# Each matrix is for a zeta**i factor, where zeta is the n-th root of unity.
	# And n = calc.matrixCountTrans.
	assert len(ms) == calc.matrixCountTrans
	order = len(ms)

	K = CyclotomicField(order)
	zeta = K.gen()
	Kcoords = zeta.coordinates_in_terms_of_powers()

	assert len(K.power_basis()) == K.degree()
	new_ms = [matrix(QQ, ms[0].nrows(), ms[0].ncols()) for i in range(K.degree())]
	for l in range(order):
		coords = Kcoords(zeta**l)
		for i,m in enumerate(coords):
			new_ms[i] += ms[l] * m
	ms = new_ms

	denom = calc.matrixRowDenomTrans
	denom, ms = reduceNRow(denom=denom, mats=ms)

	return denom, order, ms
예제 #2
0
def toLowerCyclBase(ms, old_order, new_order):
	"""
	Let's

		K_old = CyclotomicField(old_order) ,
		K_new = CyclotomicField(new_order) .

	We transform the matrices in power base from `K_old` to `K_new`.

	The way this is implemented works only if `old_order`
	is a multiple of `new_order`.

	INPUT:

	- `ms` -- A list of matrices where every matrix is a factor to
	          `zeta_old**i` where `zeta_old = K_old.gen()`
	          and `len(ms) == K_old.degree()`.

	- `old_order` -- The order of `K_old`.

	- `new_order` -- The order of `K_new`.

	OUTPUT:

	- A list of matrices `new_ms` where every matrix is a factor to
	  `zeta_new**i` where `zeta_new = K_new.gen()` and
	  `len(new_ms) == K_new.degree()`.

	"""

	assert isinstance(ms, list) # list of matrices
	assert old_order % new_order == 0

	K_old = CyclotomicField(old_order)
	old_degree = int(ZZ(K_old.degree()))
	K_new = CyclotomicField(new_order)
	new_degree = int(ZZ(K_new.degree()))
	assert old_degree % new_degree == 0
	assert len(ms) == old_degree

	new_ms = [None] * new_degree
	for i in range(old_degree):
		i2,rem = divmod(i, old_degree / new_degree)
		if rem == 0:
			new_ms[i2] = ms[i]
		else:
			if ms[i] != 0:
				return None
	return new_ms
예제 #3
0
def toCyclPowerBase(M, order):
	"""
	Let's

		K = CyclotomicField(order).

	INPUT:

	- `M` -- A matrix over the cyclomotic field `K`.

	- `order` -- The order of `K`, the cyclomotic field.

	OUTPUT:

	- A list of matrices `ms` in power base where every matrix
	  is a factor to `zeta**i` where `zeta = K.gen()`
	  and `len(ms) == K.degree()`.

	"""

	K = CyclotomicField(order)
	zeta = K.gen()
	Kcoords = zeta.coordinates_in_terms_of_powers()

	assert len(K.power_basis()) == K.degree()
	ms = [matrix(QQ,M.nrows(),M.ncols()) for i in range(K.degree())]
	for y in range(M.nrows()):
		for x in range(M.ncols()):
			try:
				v_ = M[y,x]
				v = K(v_)
				coords = Kcoords(v)
			except TypeError:
				print "type of {1} ({2}) is not valid in Cyclomotic field of order {0}".format(order, M[y,x], type(M[y,x]))
				raise
			assert len(coords) == K.degree()
			for i in range(K.degree()):
				ms[i][y,x] = coords[i]
	return ms