[DEV] Add capability of the mathematic element of etk system

This commit is contained in:
Edouard DUPIN 2012-10-29 18:06:40 +01:00
parent 98f1efe59f
commit ad78c67548
11 changed files with 863 additions and 21 deletions

2
Build

@ -1 +1 @@
Subproject commit e7fece47d728bcb6195ecbb2c6d78bd9be04e33d
Subproject commit 4016ab8885720c1e9117c7f9542f7c6d3f3e4bd3

View File

@ -23,8 +23,18 @@ Dependency packages
sudo apt-get install realpath
License (DSB like)
==================
Copyright (c)
=============
Note : only for etk and EWOL
2011, Edouard DUPIN
License (DSB)
=============
Note : only for etk and EWOL
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

@ -1 +1 @@
Subproject commit 4c65a1049ab5f6d97f225ba44394c6b6444eddd7
Subproject commit 9ca566ed85228973d9e442ee41d14d59e494a087

View File

@ -1,6 +1,6 @@
/**
*******************************************************************************
* @file etk/Matix.h
* @file etk/math/Matix.h
* @brief Ewol Tool Kit : generique Matrix type (header)
* @author Edouard DUPIN
* @date 29/08/2012
@ -253,6 +253,9 @@ namespace etk {
T* operator[] (int32_t line) {
return &m_data[line*m_size.x];
}
/*****************************************************
* Other mathematical function
*****************************************************/
/**
* @ brief Transpose Matrix
* @ return the transpose matrix
@ -268,6 +271,39 @@ namespace etk {
}
return tmpMatrix;
};
/**
* @ brief Create a convolution on the matrix : set convolution on the lines
* @ param[in] obj The convolution operator
* @ return the value of the convolution
*/
Matrix<T> Convolution(Matrix<T>& obj)
{
Matrix<T> tmppp(1,1);
// TODO : ...
return tmppp;
};
/**
* @ brief generate a devide of the curent Matrix with the specify power of 2
* @ param[in] decalage The power of 2 of the division
* @ return the result
*/
Matrix<T>& Fix(int32_t decalage)
{
Matrix<T> tmppp(1,1);
// TODO : ...
return tmppp;
};
/**
* @ brief generate a devide of the curent Matrix with the specify power of 2
* @ param[in] decalage The power of 2 of the division
* @ return the result
*/
Matrix<T>& Round2(int32_t decalage)
{
Matrix<T> tmppp(1,1);
// TODO : ...
return tmppp;
};
/*****************************************************
* other stupid action :
*****************************************************/

View File

@ -0,0 +1,247 @@
/**
*******************************************************************************
* @file etk/math/Plane.h
* @brief Ewol Tool Kit : generique plane type (header)
* @author Edouard DUPIN
* @date 29/10/2012
* @par Project
* Ewol TK
*
* @par Copyright
* Copyright 2011 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
*
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#ifndef __ETK_TYPES_PLANE_H__
#define __ETK_TYPES_PLANE_H__
#include <etk/DebugInternal.h>
#include <etk/math/Vector3D.h>
#include <etk/Vector.h>
namespace etk {
template <typename T> class Plane
{
public :
//member variables
etk::Vector3D<T> m_normal; //X.N+intercept=0
T m_intercept;
public:
/*****************************************************
* Constructor
*****************************************************/
Plane(void) :
m_normal(0, 0, 0),
m_intercept(0)
{
}
Plane(etk::Vector3D<T> _normal, T _intercept=0) :
m_normal(_normal),
m_intercept(_intercept)
{
}
Plane(const Plane& obj) :
m_normal(obj.m_normal),
m_intercept(obj.m_intercept)
{
}
/*****************************************************
* Destructor
*****************************************************/
~Plane(void)
{
};
/**
* @brief
* @param[in,out]
* @return
*/
void SetNormal(const etk::Vector3D<T>& obj)
{
m_normal=obj;
};
/**
* @brief
* @param[in,out]
* @return
*/
void SetIntercept(float _intercept)
{
m_intercept=_intercept;
};
/**
* @brief
* @param[in,out]
* @return
*/
void SetFromPoints(const etk::Vector3D<T> & p0,
const etk::Vector3D<T> & p1,
const etk::Vector3D<T> & p2)
{
m_normal=(p1-p0).CrossProduct(p2-p0);
m_normal.Normalize();
CalculateIntercept(p0);
};
/**
* @brief
* @param[in,out]
* @return
*/
void CalculateIntercept(const etk::Vector3D<T>& pointOnPlane)
{
m_intercept=-m_normal.DotProduct(pointOnPlane);
}
/**
* @brief
* @param[in,out]
* @return
*/
void Normalize(void)
{
float normalLength=m_normal.GetLength();
m_normal/=normalLength;
m_intercept/=normalLength;
};
/**
* @brief
* @param[in,out]
* @return
*/
etk::Vector3D<T> GetNormal(void)
{
return m_normal;
};
/**
* @brief
* @param[in,out]
* @return
*/
float GetIntercept()
{
return m_intercept;
}
//find point of intersection of 3 planes
/**
* @brief
* @param[in,out]
* @return
*/
bool Intersect3(const Plane<T>& p2,
const Plane<T> & p3,
etk::Vector3D<T> & result)
{
float denominator=m_normal.DotProduct((p2.m_normal).CrossProduct(p3.m_normal));
//scalar triple product of normals
if(denominator==0.0f) {
//no intersection
return false;
}
etk::Vector3D<T> temp1, temp2, temp3;
temp1=(p2.m_normal.CrossProduct(p3.m_normal))*m_intercept;
temp2=(p3.m_normal.CrossProduct(m_normal))*p2.m_intercept;
temp3=(m_normal.CrossProduct(p2.m_normal))*p3.m_intercept;
result=(temp1+temp2+temp3)/(-denominator);
return true;
};
/**
* @brief
* @param[in,out]
* @return
*/
float GetDistance(const etk::Vector3D<T> & point) const
{
return point.x*m_normal.x
+ point.y*m_normal.y
+ point.z*m_normal.z
+ m_intercept;
};
/**
* @brief
* @param[in,out]
* @return
*/
Plane<T> LinearInterpolate(const Plane<T> & p2, float factor)
{
Plane<T> result;
result.m_normal=m_normal*(1.0f-factor) + p2.m_normal*factor;
result.m_normal.Normalize();
result.m_intercept=m_intercept*(1.0f-factor) + p2.m_intercept*factor;
return result;
};
//operators
/**
* @brief
* @param[in,out]
* @return
*/
bool operator==(const Plane<T> & obj) const
{
if( m_normal==obj.m_normal
&& m_intercept==obj.m_intercept) {
return true;
}
return false;
};
/**
* @brief
* @param[in,out]
* @return
*/
bool operator!=(const Plane<T> & obj) const
{
return!((*this)==obj);
}
//unary operators
/**
* @brief
* @param[in,out]
* @return
*/
Plane<T> operator-(void) const
{
return Plane<T>(-m_normal, -m_intercept);
}
/**
* @brief
* @param[in,out]
* @return
*/
Plane<T> operator+(void) const
{
return *this;
}
};
};
#endif

View File

@ -170,16 +170,89 @@ namespace etk
return result;
}
T QuadDist(void)
/**
* @brief Set the vector at (0,0)
*/
void Zero(void)
{
return x*x + y*y;
}
x=0;
y=0;
};
/**
* @brief Set the vector at (1,1)
*/
void One(void)
{
x=0;
y=0;
};
T Dist(void)
/**
* @brief normalize the curent vector
*/
void Normalize(void)
{
return sqrt(x*x + y*y);
}
};
float length=GetLength();
if( length==1
|| length==0) {
return;
}
float scalefactor = 1.0f/length;
x *= scalefactor;
y *= scalefactor;
};
/**
* @brief Get the normalized vector
* @return a new vector normalized
*/
Vector2D<T> GetNormalized(void) const
{
Vector2D<T> tmp(*this);
tmp.Normalize();
return tmp;
};
/**
* @brief Get the size of the vector
* @return the float value
*/
float GetLength(void) const
{
return (float)sqrt((x*x)+(y*y));
};
/**
* @brief Get the square size of the vector
* @return flat value
*/
float GetSquaredLength(void) const
{
return (float)(x*x)+(y*y);
};
/**
* @brief Linar intermolation of the curent Vector
* @param[in] input
* @param[in] factor
* @return the interpolate vector
*/
Vector2D<T> LinearInterpolate(const Vector2D<T> & input, float factor) const
{
return (*this)*(1.0f-factor) + input*factor;
};
/**
* @brief Quadratic intermolation of the curent Vector
* @param[in] v1
* @param[in] v2
* @param[in] factor
* @return the interpolate vector
*/
Vector2D<T> QuadraticInterpolate(const Vector2D<T> & v2, const Vector2D<T> & v3, float factor) const
{
return (*this)*(1.0f-factor)*(1.0f-factor) + 2*v2*factor*(1.0f-factor) + v3*factor*factor;}
};
};
#endif

View File

@ -81,6 +81,12 @@ namespace etk
z += (T)obj.z;
return *this;
}
const Vector3D<T>& operator+= (const float val) {
x += val;
y += val;
z += val;
return *this;
}
/*****************************************************
* + operator
*****************************************************/
@ -91,6 +97,13 @@ namespace etk
tmpp.z += (T)obj.z;
return *this;
}
Vector3D<T> operator+ (const float val) {
Vector3D<T> tmpp(x,y,y);
tmpp.x += val;
tmpp.y += val;
tmpp.z += val;
return *this;
}
/*****************************************************
* -= operator
*****************************************************/
@ -100,6 +113,12 @@ namespace etk
z -= (T)obj.z;
return *this;
}
const Vector3D<T>& operator-= (const float val) {
x -= val;
y -= val;
z -= val;
return *this;
}
/*****************************************************
* - operator
*****************************************************/
@ -110,13 +129,35 @@ namespace etk
tmpp.z -= (T)obj.z;
return *this;
}
Vector3D<T> operator- (const float val) {
Vector3D<T> tmpp(x,y,y);
tmpp.x -= val;
tmpp.y -= val;
tmpp.z -= val;
return *this;
}
/*****************************************************
* /= operator
*****************************************************/
const Vector3D<T>& operator/= (const Vector3D<T>& obj) {
x /= (T)obj.x;
y /= (T)obj.y;
z /= (T)obj.z;
if (obj.x != 0) {
x /= (T)obj.x;
}
if (obj.y != 0) {
y /= (T)obj.y;
}
if (obj.z != 0) {
z /= (T)obj.z;
}
return *this;
}
const Vector3D<T>& operator/= (const float val) {
if (val==0) {
return *this;
}
x /= val;
y /= val;
z /= val;
return *this;
}
/*****************************************************
@ -124,10 +165,26 @@ namespace etk
*****************************************************/
Vector3D<T> operator/ (const Vector3D<T>& obj) {
Vector3D<T> tmpp(x,y,y);
tmpp.x /= (T)obj.x;
tmpp.y /= (T)obj.y;
tmpp.z /= (T)obj.z;
return *this;
if (obj.x != 0) {
tmpp.x /= (T)obj.x;
}
if (obj.y != 0) {
tmpp.y /= (T)obj.y;
}
if (obj.z != 0) {
tmpp.z /= (T)obj.z;
}
return tmpp;
}
Vector3D<T> operator/ (const float val) {
Vector3D<T> tmpp(x,y,y);
if (val==0) {
return tmpp;
}
tmpp.x /= val;
tmpp.y /= val;
tmpp.z /= val;
return tmpp;
}
/*****************************************************
* *= operator
@ -138,6 +195,12 @@ namespace etk
z *= (T)obj.z;
return *this;
}
const Vector3D<T>& operator*= (const float val) {
x *= val;
y *= val;
z *= val;
return *this;
}
/*****************************************************
* * operator
*****************************************************/
@ -146,7 +209,14 @@ namespace etk
tmpp.x *= (T)obj.x;
tmpp.y *= (T)obj.y;
tmpp.z *= (T)obj.z;
return *this;
return tmpp;
}
Vector3D<T> operator* (const float val) {
Vector3D<T> tmpp(x,y,y);
tmpp.x *= val;
tmpp.y *= val;
tmpp.z *= val;
return tmpp;
}
/*****************************************************
* ++ operator
@ -180,6 +250,168 @@ namespace etk
--(*this);
return result;
}
void Zero(void)
{
x=0;
y=0;
z=0;
};
void One(void)
{
x=1;
y=1;
z=1;
};
//vector algebra
Vector3D<T> CrossProduct(const Vector3D<T>& obj) const
{
return Vector3D<T>( y*obj.z - z*obj.y,
z*obj.x - x*obj.z,
x*obj.y - y*obj.x);
};
float DotProduct(const Vector3D<T>& obj) const
{
return x*obj.x
+ y*obj.y
+ z*obj.z;
};
void Normalize()
{
float length=GetLength();
if(length==1 || length==0) {
return;
}
float scalefactor = 1.0f/length;
x *= scalefactor;
y *= scalefactor;
z *= scalefactor;
};
Vector3D<T> GetNormalized() const
{
Vector3D<T> tmpp(*this);
tmpp.Normalize();
return tmpp;
};
float GetLength() const
{
return (float)sqrt((x*x)+(y*y)+(z*z));
};
float GetSquaredLength() const
{
return (x*x)+(y*y)+(z*z);
};
//rotations
void RotateX(double angle)
{
(*this)=GetRotatedX(angle);
};
Vector3D<T> GetRotatedX(double angle) const
{
if(angle==0.0) {
return (*this);
}
float sinAngle=(float)sin(M_PI*angle/180);
float cosAngle=(float)cos(M_PI*angle/180);
return Vector3D<T>( x,
y*cosAngle - z*sinAngle,
y*sinAngle + z*cosAngle);
};
void RotateY(double angle)
{
(*this)=GetRotatedY(angle);
};
Vector3D<T> GetRotatedY(double angle) const
{
if(angle==0.0) {
return (*this);
}
float sinAngle=(float)sin(M_PI*angle/180);
float cosAngle=(float)cos(M_PI*angle/180);
return Vector3D<T>( x*cosAngle + z*sinAngle,
y,
-x*sinAngle + z*cosAngle);
};
void RotateZ(double angle)
{
(*this)=GetRotatedZ(angle);
};
Vector3D<T> GetRotatedZ(double angle) const
{
if(angle==0.0) {
return (*this);
}
float sinAngle=(float)sin(M_PI*angle/180);
float cosAngle=(float)cos(M_PI*angle/180);
return Vector3D<T>( x*cosAngle - y*sinAngle,
x*sinAngle + y*cosAngle,
z);
};
void RotateAxis(double angle, const Vector3D<T> & axis)
{
(*this)=GetRotatedAxis(angle, axis);
};
Vector3D<T> GetRotatedAxis(double angle, const Vector3D<T> & axis) const
{
if(angle==0.0) {
return (*this);
}
Vector3D<T> u=axis.GetNormalized();
Vector3D<T> rotMatrixRow0, rotMatrixRow1, rotMatrixRow2;
float sinAngle=(float)sin(M_PI*angle/180);
float cosAngle=(float)cos(M_PI*angle/180);
float MinusCosAngle=1.0f-cosAngle;
rotMatrixRow0.x=(u.x)*(u.x) + cosAngle*(1-(u.x)*(u.x));
rotMatrixRow0.y=(u.x)*(u.y)*(MinusCosAngle) - sinAngle*u.z;
rotMatrixRow0.z=(u.x)*(u.z)*(MinusCosAngle) + sinAngle*u.y;
rotMatrixRow1.x=(u.x)*(u.y)*(MinusCosAngle) + sinAngle*u.z;
rotMatrixRow1.y=(u.y)*(u.y) + cosAngle*(1-(u.y)*(u.y));
rotMatrixRow1.z=(u.y)*(u.z)*(MinusCosAngle) - sinAngle*u.x;
rotMatrixRow2.x=(u.x)*(u.z)*(MinusCosAngle) - sinAngle*u.y;
rotMatrixRow2.y=(u.y)*(u.z)*(MinusCosAngle) + sinAngle*u.x;
rotMatrixRow2.z=(u.z)*(u.z) + cosAngle*(1-(u.z)*(u.z));
return Vector3D<T>( this->DotProduct(rotMatrixRow0),
this->DotProduct(rotMatrixRow1),
this->DotProduct(rotMatrixRow2));
};
/**
* @brief Linar intermolation of the curent Vector
* @param[in] input
* @param[in] factor
* @return the interpolate vector
*/
Vector3D<T> LinearInterpolate(const Vector3D<T>& input, float factor) const
{
return (*this)*(1.0f-factor) + input*factor;
};
/**
* @brief Quadratic intermolation of the curent Vector
* @param[in] v1
* @param[in] v2
* @param[in] factor
* @return the interpolate vector
*/
Vector3D<T> QuadraticInterpolate(const Vector3D<T>& v2, const Vector3D<T>& v3, float factor) const
{
return (*this)*(1.0f-factor)*(1.0f-factor) + 2*v2*factor*(1.0f-factor) + v3*factor*factor;
};
};
};

View File

@ -27,7 +27,178 @@
namespace etk
{
//template <typename T> class Vector4D
template <typename T> class Vector4D
{
public:
T x;
T y;
union {
T z;
T width;
};
union {
T w;
T height;
};
public:
/*****************************************************
* Constructor
*****************************************************/
Vector4D(void) : x(0), y(0), z(0), w(0) { };
Vector4D(double _x, double _y, double _z, double _w) : x(_x), y(_y), z(_z), w(_w) { };
Vector4D(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) { };
Vector4D(int32_t _x, int32_t _y, int32_t _z, int32_t _w) : x(_x), y(_y), z(_z), w(_w) { };
Vector4D(const Vector4D<double>& obj) : x((T)obj.x), y((T)obj.y), z((T)obj.z), w((T)obj.w) { };
Vector4D(const Vector4D<float>& obj) : x((T)obj.x), y((T)obj.y), z((T)obj.z), w((T)obj.w) { };
Vector4D(const Vector4D<int32_t>& obj) : x((T)obj.x), y((T)obj.y), z((T)obj.z), w((T)obj.w) { };
~Vector4D(void) { };
/*****************************************************
* = assigment
*****************************************************/
const Vector4D<T>& operator= (const Vector4D<T>& obj ) {
x = (T)obj.x;
y = (T)obj.y;
z = (T)obj.z;
w = (T)obj.w;
return *this;
}
/*****************************************************
* == operator
*****************************************************/
bool operator== (const Vector4D<T>& obj) const {
if ((T)obj.x == x && (T)obj.y == y && (T)obj.z == z) {
return true;
}
return false;
}
/*****************************************************
* != operator
*****************************************************/
bool operator!= (const Vector4D<T>& obj) const {
if ((T)obj.x == x && (T)obj.y == y && (T)obj.z == z && (T)obj.w == w) {
return false;
}
return true;
}
/*****************************************************
* += operator
*****************************************************/
const Vector4D<T>& operator+= (const Vector4D<T>& obj) {
x += (T)obj.x;
y += (T)obj.y;
z += (T)obj.z;
w += (T)obj.w;
return *this;
}
/*****************************************************
* + operator
*****************************************************/
Vector4D<T> operator+ (const Vector4D<T>& obj) {
Vector4D<T> tmpp(x,y,y);
tmpp.x += (T)obj.x;
tmpp.y += (T)obj.y;
tmpp.z += (T)obj.z;
tmpp.w += (T)obj.w;
return *this;
}
/*****************************************************
* -= operator
*****************************************************/
const Vector4D<T>& operator-= (const Vector4D<T>& obj) {
x -= (T)obj.x;
y -= (T)obj.y;
z -= (T)obj.z;
w -= (T)obj.w;
return *this;
}
/*****************************************************
* - operator
*****************************************************/
Vector4D<T> operator- (const Vector4D<T>& obj) {
Vector4D<T> tmpp(x,y,y);
tmpp.x -= (T)obj.x;
tmpp.y -= (T)obj.y;
tmpp.z -= (T)obj.z;
tmpp.w -= (T)obj.w;
return *this;
}
/*****************************************************
* /= operator
*****************************************************/
const Vector4D<T>& operator/= (const Vector4D<T>& obj) {
x /= (T)obj.x;
y /= (T)obj.y;
z /= (T)obj.z;
w /= (T)obj.w;
return *this;
}
/*****************************************************
* / operator
*****************************************************/
Vector4D<T> operator/ (const Vector4D<T>& obj) {
Vector4D<T> tmpp(x,y,y);
tmpp.x /= (T)obj.x;
tmpp.y /= (T)obj.y;
tmpp.z /= (T)obj.z;
tmpp.w /= (T)obj.w;
return *this;
}
/*****************************************************
* *= operator
*****************************************************/
const Vector4D<T>& operator*= (const Vector4D<T>& obj) {
x *= (T)obj.x;
y *= (T)obj.y;
z *= (T)obj.z;
w *= (T)obj.w;
return *this;
}
/*****************************************************
* * operator
*****************************************************/
Vector4D<T> operator* (const Vector4D<T>& obj) {
Vector4D<T> tmpp(x,y,y);
tmpp.x *= (T)obj.x;
tmpp.y *= (T)obj.y;
tmpp.z *= (T)obj.z;
tmpp.w *= (T)obj.w;
return *this;
}
/*****************************************************
* ++ operator
*****************************************************/
Vector4D<T>& operator++() // prefix
{
++x;
++y;
++z;
++w;
return *this;
}
Vector4D<T> operator++(int unused) // postfix
{
Vector4D<T> result = *this;
++(*this);
return result;
}
/*****************************************************
* -- operator
*****************************************************/
Vector4D<T>& operator--() // prefix
{
--x;
--y;
--z;
--w;
return *this;
}
Vector4D<T> operator--(int unused) // postfix
{
Vector4D<T> result = *this;
--(*this);
return result;
}
};
};
#endif

View File

@ -22,6 +22,9 @@
*******************************************************************************
*/
#ifndef EPSILON
#define EPSILON 0.01f
#endif
#include <math.h>
#include <etk/math/Vector2D.h>

View File

@ -0,0 +1,35 @@
Copyright (c)
=============
2011, Edouard DUPIN
License (DSB)
=============
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The name of the author may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,35 @@
Copyright (c)
=============
2011, Edouard DUPIN
License (DSB)
=============
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
3. The name of the author may not be used to endorse or promote
products derived from this software without specific prior
written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.