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
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
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