/***************************************************************************
 *   Copyright (C) 2008 by Peter Eschright                                 *
 *   petereschright@gmail.com                                              *
 *                                                                         *
 *   This source code is presented for informational purposes only.        *
 *   Please contact the author for permision for use.                      *
 **************************************************************************/

#ifndef QUATERNION_H
#define QUATERNION_H

// /////////////////////////////////////////////////////////////
//
// File name: quaternion.h
// File description: header file for a quaternion class
//
// /////////////////////////////////////////////////////////////

#include <iostream>
#include <cstdlib>
#include <cmath>

using namespace std;

// /////////////////////////////////////////////////////////////
//  This Class implements quaternions of the form:
//     x + y*i + z*j + w*k
//
//  Where x,y,z,w are coefficients to the units 1,i,j, and k.
//
//  The following relations hold:
//  
//     i^2 = j^2 = k^2 = -1
//     ij = -ji = k
//     jk = -kj = i
//     ki = -ik = j
//
//  Addition is componentwise.
//  Multiplication can be summerized in the following table:
//     +---++---+---+---+---+
//     | * || 1 | i | j | k |
//     +===++===+===+===+===+
//     | 1 || 1 | i | j | k |
//     +---++---+---+---+---+
//     | i || i |-1 | k |-j |
//     +---++---+---+---+---+
//     | j || j |-k |-1 | i |
//     +---++---+---+---+---+
//     | k || k | j |-i |-1 |
//     +---++---+---+---+---+
//
// /////////////////////////////////////////////////////////////

class quaternion{
   
   
   // display, print
   friend ostream& operator<<(ostream&, const quaternion&);
   
   // scaler multiplication
   friend quaternion operator*(const double, const quaternion&);
   friend quaternion operator*(const quaternion&, const double);
   
   //innerproduct
   friend double inner_product(const quaternion&, const quaternion&);
   
   // addition
   friend quaternion operator+(const quaternion&, const quaternion&);
   
   // subtraction
   friend quaternion operator-(const quaternion&, const quaternion&);
   
   // multiplication
   friend quaternion operator*(const quaternion&, const quaternion&);
   
   // equality relation
   friend bool operator==(const quaternion&, const quaternion&);
   
   
   
   public:
      // constructors
      quaternion();
      quaternion(double a, double b, double c, double d);
      quaternion(const quaternion&);
      
      // assignment
      const quaternion& operator=(const quaternion&);
      
      // part-wise access
      double get_real_part();
      double set_real_part(double);
      double get_i_part();
      double set_i_part(double);
      double get_j_part();
      double set_j_part(double);
      double get_k_part();
      double set_k_part(double);
      
      // norm
      // return the norm defined as:
      // x^2 + Y^2 + z^2 + w^2
      double norm();
      
      // unit
      // get a quaternion of unit norm parellel to this one
      quaternion unit();
      
      // conjugate
      // return the conjugate defined as:
      // x - Y*i - z*j - w*k
      quaternion conjugate();
      
   private:
      double x,y,z,w;
};


#endif