Path: blob/master/src/sage/modular/arithgroup/sl2z.hpp
8820 views
//****************************************************************************1// Copyright (C) 2011 Hartmut Monien <[email protected]>2//3// Distributed under the terms of the GNU General Public License (GPL)4//5// This code is distributed in the hope that it will be useful,6// but WITHOUT ANY WARRANTY; without even the implied warranty of7// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU8// General Public License for more details.9//10// The full text of the GPL is available at:11//12// http://www.gnu.org/licenses/13//****************************************************************************1415#ifndef SL2Z_HPP_16#define SL2Z_HPP_1718#include <iostream>19#include <iomanip>20#include <cassert>21#include <gmpxx.h>2223class SL2Z {24public:25typedef mpz_class ElementType;26protected:27ElementType M[2][2];28public:29const static SL2Z E, R, T, S, U, I;30SL2Z(int a_, int b_, int c_, int d_);31SL2Z(const ElementType& a_, const ElementType& b_,32const ElementType& c_, const ElementType& d_);33SL2Z(const SL2Z&);34ElementType a() const { return M[0][0]; };35ElementType b() const { return M[0][1]; };36ElementType c() const { return M[1][0]; };37ElementType d() const { return M[1][1]; };38SL2Z inverse() const;39SL2Z operator-() const;40SL2Z operator*=(const SL2Z& x);41SL2Z operator/=(const SL2Z& x);42SL2Z mod(const size_t) const;43friend bool operator==(const SL2Z&, const SL2Z&);44friend bool operator!=(const SL2Z&, const SL2Z&);45friend SL2Z operator*(const SL2Z&, const SL2Z&);46friend SL2Z operator/(const SL2Z&, const SL2Z&);47friend std::ostream& operator<<(std::ostream&, const SL2Z&);48friend std::istream& operator>>(std::istream&, SL2Z&);49};5051inline52SL2Z::SL2Z(const SL2Z::ElementType& a_, const SL2Z::ElementType& b_,53const SL2Z::ElementType& c_, const SL2Z::ElementType& d_) {54M[0][0] = a_;55M[0][1] = b_;56M[1][0] = c_;57M[1][1] = d_;58assert(M[0][0]*M[1][1] - M[0][1]*M[1][0] == 1);59}6061inline62SL2Z::SL2Z(int a_, int b_, int c_, int d_) {63M[0][0] = a_;64M[0][1] = b_;65M[1][0] = c_;66M[1][1] = d_;67assert(M[0][0]*M[1][1] - M[0][1]*M[1][0] == 1);68}6970inline71SL2Z::SL2Z(const SL2Z& x) {72M[0][0] = x.M[0][0];73M[0][1] = x.M[0][1];74M[1][0] = x.M[1][0];75M[1][1] = x.M[1][1];76}7778inline79SL2Z SL2Z::operator-() const {80return SL2Z(-M[0][0],-M[0][1],-M[1][0],-M[1][1]);81}8283inline84SL2Z SL2Z::operator*=(const SL2Z& x) {85SL2Z result(M[0][0]*x.M[0][0] + M[0][1]*x.M[1][0],86M[0][0]*x.M[0][1] + M[0][1]*x.M[1][1],87M[1][0]*x.M[0][0] + M[1][1]*x.M[1][0],88M[1][0]*x.M[0][1] + M[1][1]*x.M[1][1]);89M[0][0] = result.M[0][0];90M[0][1] = result.M[0][1];91M[1][0] = result.M[1][0];92M[1][1] = result.M[1][1];93return *this;94}9596inline97SL2Z SL2Z::operator/=(const SL2Z& x) {98SL2Z result( M[0][0]*x.M[1][1] - M[0][1]*x.M[1][0],99-M[0][0]*x.M[0][1] + M[0][1]*x.M[0][0],100M[1][0]*x.M[1][1] - M[1][1]*x.M[1][0],101-M[1][0]*x.M[0][1] + M[1][1]*x.M[0][0]);102M[0][0] = result.M[0][0];103M[0][1] = result.M[0][1];104M[1][0] = result.M[1][0];105M[1][1] = result.M[1][1];106return *this;107}108109inline110SL2Z SL2Z::inverse() const {111return SL2Z(M[1][1], -M[0][1], -M[1][0], M[0][0]);112}113114inline115SL2Z SL2Z::mod(const size_t n) const {116return SL2Z(M[0][0]%n, M[0][1]%n, M[1][0]%n, M[1][1]%n);117}118119inline120SL2Z operator*(const SL2Z& x, const SL2Z& y) {121return SL2Z(x.M[0][0]*y.M[0][0] + x.M[0][1]*y.M[1][0],122x.M[0][0]*y.M[0][1] + x.M[0][1]*y.M[1][1],123x.M[1][0]*y.M[0][0] + x.M[1][1]*y.M[1][0],124x.M[1][0]*y.M[0][1] + x.M[1][1]*y.M[1][1]);125}126127inline128SL2Z operator/(const SL2Z& x, const SL2Z& y) {129return SL2Z( x.M[0][0]*y.M[1][1] - x.M[0][1]*y.M[1][0],130-x.M[0][0]*y.M[0][1] + x.M[0][1]*y.M[0][0],131x.M[1][0]*y.M[1][1] - x.M[1][1]*y.M[1][0],132-x.M[1][0]*y.M[0][1] + x.M[1][1]*y.M[0][0]);133}134135inline136bool operator==(const SL2Z& x, const SL2Z& y) {137return (x.M[0][0] == y.M[0][0] and138x.M[0][1] == y.M[0][1] and139x.M[1][0] == y.M[1][0] and140x.M[1][1] == y.M[1][1]);141}142143inline144bool operator!=(const SL2Z& x, const SL2Z& y) {145return not (x == y);146}147148inline149std::ostream& operator<<(std::ostream& os, const SL2Z& x) {150os << "["151<< x.M[0][0] << ", "152<< x.M[0][1] << "; "153<< x.M[1][0] << ", "154<< x.M[1][1]155<< "]";156return os;157}158159inline160std::istream& operator>>(std::istream& is, SL2Z& x) {161char c;162is >> c;163if( c == '[' ) {164is >> x.M[0][0] >> c;165if( c == ',' ) {166is >> x.M[0][1] >> c;167if( c == ';' ) {168is >> x.M[1][0] >> c;169if( c == ',' ) {170is >> x.M[1][1] >> c;171if( c != ']' ) is.clear(std::ios_base::badbit);172} else {173is.clear(std::ios_base::badbit);174}175} else {176is.clear(std::ios_base::badbit);177}178} else {179is.clear(std::ios_base::badbit);180}181} else {182is.clear(std::ios_base::badbit);183}184return is;185}186187#endif // SL2Z_HPP_188189190