amath/src/lib/cplex.cpp

567 lines
11 KiB
C++

/*-
* Copyright (c) 2014-2017 Carsten Sonne Larsen <cs@innolan.net>
* All rights reserved.
*
* 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.
*
* 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.
*
* Project homepage:
* http://amath.innolan.net
*
*/
#include "math.h"
#include "complex.h"
#include "real.h"
#include "cplex.h"
#include "nnumb.h"
#include "integer.h"
ComplexNumber::ComplexNumber() :
Number(nsyscomplex)
{
z = cpack(0.0, 0.0);
}
ComplexNumber::ComplexNumber(complex z) :
Number(nsyscomplex)
{
this->z = z;
}
ComplexNumber::ComplexNumber(double real, double imag) :
Number(nsyscomplex)
{
z = cpack(real, imag);
}
ComplexNumber::~ComplexNumber()
{
}
Number* ComplexNumber::Clone()
{
return new ComplexNumber(z);
}
int ComplexNumber::GetIntegerValue()
{
return static_cast<int>(creal(z));
}
double ComplexNumber::GetRealValue()
{
return creal(z);
}
double ComplexNumber::GetImagValue() const
{
return cimag(z);
}
complex ComplexNumber::GetComplexValue() const
{
return z;
}
bool ComplexNumber::PureComplexValue()
{
return (creal(z) == 0.0);
}
int ComplexNumber::GetPrecedence()
{
if ((creal(z) < 0.0) || (creal(z) == 0.0 && cimag(z) < 0.0))
{
return -1;
}
else if (creal(z) != 0.0 && cimag(z) != 0.0)
{
return 2;
}
else
{
return 0;
}
}
int ComplexNumber::GetDefaultPrecedence()
{
return (creal(z) != 0.0 && cimag(z) != 0.0) ? 2 : 0;
}
bool ComplexNumber::IsZero()
{
return (creal(z) == 0.0 && cimag(z) == 0.0);
}
bool ComplexNumber::IsTooSmall()
{
return (creal(z) > 0 && creal(z) < D_INFN) ||
(creal(z) < 0 && creal(z) > -D_INFN) ||
(cimag(z) > 0 && cimag(z) < D_INFN) ||
(cimag(z) < 0 && cimag(z) > -D_INFN);
}
bool ComplexNumber::IsTooLarge()
{
return (creal(z) > D_INFP) || (cimag(z) > D_INFP);
}
bool ComplexNumber::IsNaN()
{
return false;
}
bool ComplexNumber::IsNotImplemented()
{
return false;
}
Number* ComplexNumber::Unary()
{
complex w = cpack(-creal(z), -cimag(z));
return new ComplexNumber(w);
}
Number* ComplexNumber::Add(Number* other)
{
if (other->IsNaN())
return new NonNumber(nnnan);
if (other->system == nsyscomplex)
{
ComplexNumber* w = static_cast<ComplexNumber*>(other);
return new ComplexNumber(cadd(z, w->z));
}
if (other->system == nsysreal)
{
RealNumber* a = static_cast<RealNumber*>(other);
return new ComplexNumber(cadd(z, cpack(a->x, 0.0)));
}
if (other->system == nsysinteger)
{
IntegerNumber* a = static_cast<IntegerNumber*>(other);
return new ComplexNumber(cadd(z, cpack(static_cast<double>(a->i), 0.0)));
}
return new ComplexNumber();
}
Number* ComplexNumber::Sub(Number* other)
{
if (other->IsNaN())
return new NonNumber(nnnan);
if (other->system == nsyscomplex)
{
ComplexNumber* w = static_cast<ComplexNumber*>(other);
return new ComplexNumber(csub(z, w->z));
}
if (other->system == nsysreal)
{
RealNumber* a = static_cast<RealNumber*>(other);
return new ComplexNumber(csub(z, cpack(a->x, 0.0)));
}
if (other->system == nsysinteger)
{
IntegerNumber* a = static_cast<IntegerNumber*>(other);
return new ComplexNumber(csub(z, cpack(static_cast<double>(a->i), 0.0)));
}
return new ComplexNumber();
}
Number* ComplexNumber::Mul(Number* other)
{
if (other->IsNaN())
return new NonNumber(nnnan);
if (other->system == nsyscomplex)
{
ComplexNumber* w = static_cast<ComplexNumber*>(other);
return new ComplexNumber(cmul(z, w->z));
}
if (other->system == nsysreal)
{
RealNumber* a = static_cast<RealNumber*>(other);
return new ComplexNumber(cmul(z, cpack(a->x, 0.0)));
}
if (other->system == nsysinteger)
{
IntegerNumber* a = static_cast<IntegerNumber*>(other);
return new ComplexNumber(cmul(z, cpack(static_cast<double>(a->i), 0.0)));
}
return new ComplexNumber();
}
Number* ComplexNumber::Div(Number* other)
{
if (other->IsZero() || other->IsNaN())
return new NonNumber(nnnan);
if (other->system == nsyscomplex)
{
ComplexNumber* w = static_cast<ComplexNumber*>(other);
return new ComplexNumber(cdiv(z, w->z));
}
if (other->system == nsysreal)
{
RealNumber* a = static_cast<RealNumber*>(other);
return new ComplexNumber(cdiv(z, cpack(a->x, 0.0)));
}
if (other->system == nsysinteger)
{
IntegerNumber* a = static_cast<IntegerNumber*>(other);
return new ComplexNumber(cdiv(z, cpack(static_cast<double>(a->i), 0.0)));
}
return new ComplexNumber();
}
Number* ComplexNumber::Raise(Number* exponent)
{
if (exponent->IsNaN())
return new NonNumber(nnnan);
if (exponent->system == nsyscomplex)
{
ComplexNumber* w = static_cast<ComplexNumber*>(exponent);
return new ComplexNumber(cpow(z, w->z));
}
if (exponent->system == nsysreal)
{
RealNumber* a = static_cast<RealNumber*>(exponent);
return new ComplexNumber(cpow(z, cpack(a->x, 0.0)));
}
if (exponent->system == nsysinteger)
{
IntegerNumber* a = static_cast<IntegerNumber*>(exponent);
return new ComplexNumber(cpow(z, cpack(static_cast<double>(a->i), 0.0)));
}
return new ComplexNumber();
}
Number* ComplexNumber::Factorial()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::Signum()
{
return new RealNumber(csgn(z));
}
Number* ComplexNumber::Absolute()
{
return new RealNumber(cabs(z));
}
Number* ComplexNumber::Trunc()
{
return new ComplexNumber(ctrunc(z));
}
Number* ComplexNumber::Round()
{
return new ComplexNumber(cround(z));
}
Number* ComplexNumber::Floor()
{
return new ComplexNumber(cfloor(z));
}
Number* ComplexNumber::Ceiling()
{
return new ComplexNumber(cceil(z));
}
Number* ComplexNumber::SquareRoot()
{
return new ComplexNumber(csqrt(z));
}
Number* ComplexNumber::Reciprocal()
{
return new ComplexNumber(creci(z));
}
Number* ComplexNumber::CubeRoot()
{
return new ComplexNumber(ccbrt(z));
}
Number* ComplexNumber::Log()
{
if (creal(z) == 0.0 && cimag(z) == 0.0)
return new NonNumber(nnnan);
return new ComplexNumber(clog(z));
}
Number* ComplexNumber::Log2()
{
if (creal(z) == 0.0 && cimag(z) == 0.0)
return new NonNumber(nnnan);
return new ComplexNumber(clogb(z));
}
Number* ComplexNumber::Log10()
{
if (creal(z) == 0.0 && cimag(z) == 0.0)
return new NonNumber(nnnan);
return new ComplexNumber(clog10(z));
}
Number* ComplexNumber::Sine()
{
return new ComplexNumber(csin(z));
}
Number* ComplexNumber::Cosine()
{
return new ComplexNumber(ccos(z));
}
Number* ComplexNumber::Tangent()
{
return new ComplexNumber(ctan(z));
}
Number* ComplexNumber::Secant()
{
return new ComplexNumber(csec(z));
}
Number* ComplexNumber::Cosecant()
{
return new ComplexNumber(ccsc(z));
}
Number* ComplexNumber::Cotangent()
{
return new ComplexNumber(ccot(z));
}
Number* ComplexNumber::ArcSine()
{
return new ComplexNumber(casin(z));
}
Number* ComplexNumber::ArcCosine()
{
return new ComplexNumber(cacos(z));
}
Number* ComplexNumber::ArcTangent()
{
return new ComplexNumber(catan(z));
}
Number* ComplexNumber::ArcSecant()
{
return new ComplexNumber(casec(z));
}
Number* ComplexNumber::ArcCosecant()
{
return new ComplexNumber(cacsc(z));
}
Number* ComplexNumber::ArcCotangent()
{
return new ComplexNumber(cacot(z));
}
Number* ComplexNumber::HypSine()
{
return new ComplexNumber(csinh(z));
}
Number* ComplexNumber::HypCosine()
{
return new ComplexNumber(ccosh(z));
}
Number* ComplexNumber::HypTangent()
{
return new ComplexNumber(ctanh(z));
}
Number* ComplexNumber::HypSecant()
{
return new ComplexNumber(csech(z));
}
Number* ComplexNumber::HypCosecant()
{
return new ComplexNumber(ccsch(z));
}
Number* ComplexNumber::HypCotangent()
{
return new ComplexNumber(ccoth(z));
}
Number* ComplexNumber::HypArcSine()
{
return new ComplexNumber(casinh(z));
}
Number* ComplexNumber::HypArcCosine()
{
return new ComplexNumber(cacosh(z));
}
Number* ComplexNumber::HypArcTangent()
{
return new ComplexNumber(catanh(z));
}
Number* ComplexNumber::HypArcSecant()
{
return new ComplexNumber(casech(z));
}
Number* ComplexNumber::HypArcCosecant()
{
return new ComplexNumber(cacsch(z));
}
Number* ComplexNumber::HypArcCotangent()
{
return new ComplexNumber(cacoth(z));
}
Number* ComplexNumber::VerSine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::VerCosine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::CoVerSine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::CoVerCosine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::HaVerSine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::HaVerCosine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::HaCoVerSine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::HaCoVerCosine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ArcVerSine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ArcVerCosine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ArcCoVerSine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ArcCoVerCosine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ArcHaVerSine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ArcHaVerCosine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ArcHaCoVerSine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ArcHaCoVerCosine()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ExSecant()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ExCosecant()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ArcExSecant()
{
return new NonNumber(nnnimp);
}
Number* ComplexNumber::ArcExCosecant()
{
return new NonNumber(nnnimp);
}