import math

class Quaternion:
    """
    Το τετραδόνιο quaternion είναι μια κλάση που παριστάνει αντικείμενα
    της μορφής q = a + bi + cj +dk
    """
    def __init__(self, a, b, c, d):
        """
        Αρχικοποίηση
        a: Είναι το πραγματικό μέρος
        b: Είναι ο συντελεστής του i
        c: Είναι ο συντελεστής του j
        d: Είναι ο συντελεστής του k
        """
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        
    def __str__(self):
        """
       Εδώ ο τρόπος εκτύπωσης του quaternion
        """
        return f"{self.a} + {self.b}i + {self.c}j + {self.d}k"
    def __add__(self, other):
        """
        Πρόσθεση 2 quaternions
        """
        return Quaternion(
         self.a + other.a,
         self.b + other.b,
         self.c + other.c,
         self.d + other.d
         )
    def __sub__(self, other):
        """
        Αφαιρεση 2 quaternions
        """
        return Quaternion(
        self.a - other.a,
        self.b - other.b,
        self.c - other.c,
        self.d - other.d
        )
    def __mul__(self, other):
        """
         Πολλαπλασιασμός 2 quaternions (MH ΑΝΤΙΜΕΤΑΘΕΤΙΚΟΣ)
         """
        a1, b1, c1, d1 = self.a, self.b, self.c, self.d
        a2, b2, c2, d2 = other.a, other.b, other.c, other.d

        a = a1*a2 - b1*b2 - c1*c2 - d1*d2
        b = a1*b2 + b1*a2 + c1*d2 - d1*c2
        c = a1*c2 - b1*d2 + c1*a2 + d1*b2
        d = a1*d2 + b1*c2 - c1*b2 + d1*a2

        return Quaternion(a,b,c,d)

    def sizigis(self):
        """
        Συγυγής quaternion:
        q* = a - bi -cj -dk
        """
        return Quaternion(self.a, -self.b, -self.c, -self.d)

    def norm(self):
        """
        Μέτρο (norm) quaternion:
        """
        return math.sqrt(self.a**2 + self.b**2 + self.c**2 + self.d**2)
    def inverse(self):
        """
        Αντίστροφο quaternion:
        q^-1 = q* / ||q||^2
        """
        norm_sq = self.norm() **2
        conj = self.sizigis()

        return Quaternion(
            conj.a / norm_sq,
            conj.b / norm_sq,
            conj.c / norm_sq,
            conj.d / norm_sq
            )

# ΚΥΡΙΩΣ ΠΡΟΓΡΑΜΜΑ
if __name__ == "__main__":
    #Δημιουργία 2 quaternions
    q1 = Quaternion(1, 2, 3, 4)
    q2 = Quaternion(0, 1, 0, -2)
    #Εκτύπωση
    print("q1 =", q1)
    print("q2 =", q2)
    #Πρόσθεση Αφαίρεση και πολλαπλασιασμός εμφάνιση
    print("q1 - q2 =", q1-q2)
    print("q1 * q2 =", q1*q2)
    print("Συζυγής  q1 =", q1.sizigis())
    print("Μέτρο ειναι norm =", q1.norm())
    print("Αντίστροφος q1 =", q1.inverse())

    
        
    







    




