13 #ifndef ML_QUATERNION_H
14 #define ML_QUATERNION_H
40 template <
typename DT>
93 qx(0), qy(0), qz(0), qw(0) { }
98 qx(0), qy(0), qz(0), qw(d)
106 template <
typename DT2>
109 qx =
static_cast<DT
>(q2.
qx);
110 qy =
static_cast<DT
>(q2.
qy);
111 qz =
static_cast<DT
>(q2.
qz);
112 qw =
static_cast<DT
>(q2.
qw);
154 qx(v[0]), qy(v[1]), qz(v[2]), qw(w)
213 inline void set(
const DT x,
const DT y,
const DT z,
const DT w)
234 printTemplateError(
"TQuaternion::getAsMat4() const, quaternion is not convertible to 4x4 matrix",
236 "Returning Quaterion");
239 *isConvertible =
false;
258 const DT qxqx = qx*qx;
259 const DT qyqy = qy*qy;
260 const DT qzqz = qz*qz;
262 const DT qxqy = qx*qy;
263 const DT qxqz = qx*qz;
264 const DT qxqw = qx*qw;
266 const DT qyqz = qy*qz;
267 const DT qyqw = qy*qw;
269 const DT qzqw = qz*qw;
271 const DT m11 = 1 - s * (qyqy + qzqz);
272 const DT m12 = s * (qxqy - qzqw);
273 const DT m13 = s * (qxqz + qyqw);
275 const DT m21 = s * (qxqy + qzqw);
276 const DT m22 = 1 - s * (qxqx + qzqz);
277 const DT m23 = s * (qyqz - qxqw);
279 const DT m31 = s * (qxqz - qyqw);
280 const DT m32 = s * (qyqz + qxqw);
281 const DT m33 = 1 - s * (qxqx + qyqy);
305 if (isConvertible){ *isConvertible =
true; }
322 inline DT
operator[](
const size_t i)
const {
return array[i]; }
376 qx/=d; qy/=d; qz/=d; qw/=d;
405 *isError = (b.
qx == 0) ||
412 b.
qy != 0 ? qy/b.
qy : qy,
413 b.
qz != 0 ? qz/b.
qz : qz,
414 b.
qw != 0 ? qw/b.
qw : qw) :
451 qw*p.
qw - qx*p.
qx - qy*p.
qy - qz*p.
qz); }
476 if (isError ==
nullptr){
480 "Returning unchanged quaternion");
481 retVal.
set(qx,qy,qz,qw);
486 retVal.
set(qx,qy,qz,qw);
490 if (isError !=
nullptr){ *isError =
false; }
516 inline DT
norm()
const {
return qx*qx + qy*qy + qz*qz + qw*qw; }
521 inline DT
norm2()
const {
return static_cast<DT
>(::sqrt(qx*qx + qy*qy + qz*qz + qw*qw)); }
538 if (isError ==
nullptr){
540 printTemplateError(
"TQuaternion::normalize() const, quaternion can not be normalized",
542 "Returning default quaternion");
551 if (isError){ *isError =
false; }
552 retVal.
set(qx/n, qy/n, qz/n, qw/n);
571 if (isError ==
nullptr){
575 "Returning default quaternion");
584 if (isError !=
nullptr){ *isError =
false; }
598 const DT absVal = absoluteValue();
599 if (isError !=
nullptr){
607 retVal = *
this / absVal;
613 retVal = *
this / absVal;
629 if (isInvertible==
nullptr){
632 "Returning default quaternion");
635 *isInvertible =
false;
640 if (isInvertible !=
nullptr){ *isInvertible =
true; }
641 retVal = conjugate().
mult(1/n);
657 const DT n2 = norm2();
658 const DT lqv = qv().length();
661 if (isError ==
nullptr){
663 printTemplateError(
"TQuaternion::sqrt() const, sqrt of quaternion cannot be calculated",
665 "Returning default quaternion");
674 const DT sqrtSin = ::sqrt(n2)*::sin(0.5*acos(qw/n2));
675 const DT sqrtSinF = sqrtSin*(1/lqv);
676 retVal.
set(sqrtSinF*qx, sqrtSinF*qy, sqrtSinF*qz, ::sqrt(n2) * ::cos(0.5*acos(qw/n2)));
679 if (isError !=
nullptr){ *isError =
false; }
695 const DT len = qv().length();
700 retVal =
TQuaternion<DT>((qv()/len) *
static_cast<DT
>(::sin(len)), ::cos(len)).
mult(::exp(qw));
711 const DT n2 = norm2();
712 const DT qvLen = qv().length();
714 retVal.
set(0, 0, 0, log10(n2));
718 retVal.
set(qv()/qvLen *
static_cast<DT
>(acos(qw/n2)), log10(n2));
738 const DT len = v.
length();
742 static_cast<DT
>(::cos(qw)) * v / len *
static_cast<DT
>(::sinh(len)) :
744 ::sin(qw)*::cosh(len)
754 const DT len = v.
length();
758 static_cast<DT
>(-1)*
static_cast<DT
>(::sin(qw))*qv()/len*
static_cast<DT
>(::sinh(len)) :
760 ::cos(qw)*::cosh(len)
783 const DT len = v.
length();
787 static_cast<DT
>(::cosh(qw))*v/len*
static_cast<DT
>(::sin(len)) :
789 ::sinh(qw)*::cos(len)
799 const DT len = v.
length();
803 static_cast<DT
>(::sinh(qw))*v/len*
static_cast<DT
>(::sin(len)) :
805 ::cosh(qw)*::cos(len)
813 return sinh().div(cosh(), isError);
819 return cosh().div(sinh(), isError);
848 #define _ML_QUATERNION_CALC_CHECKED(FUNC_NAME, CALC_EXPR) \
849 TQuaternion<DT> retVal; \
851 const Tvec3<DT> &v = qv(); \
852 const DT len = v.length(); \
853 if (MLValueIs0WOM(len)){ \
855 if (isError == NULL){ \
857 printTemplateError("TQuaternion::" FUNC_NAME "() const, " FUNC_NAME \
858 " of quaternion cannot be calculated", \
860 "Returning default quaternion"); \
869 if (isError != NULL){ *isError = false; } \
870 retVal = CALC_EXPR; \
878 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arcsinh());
889 #undef _ML_QUAT_CALC_EXP
894 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(arccosh());
900 #undef _ML_QUAT_CALC_EXP
905 #define _ML_QUAT_CALC_EXP TQuaternion<DT>(-v/len,0).mult(mult(TQuaternion<DT>(-v/len,0)).arctanh());
911 #undef _ML_QUAT_CALC_EXP
915 #undef _ML_QUATERNION_CALC_CHECKED
950 #ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_OPERATORS
951 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
952 ML_LA_START_NAMESPACE
959 template <
typename DT>
960 inline ML_LA_NAMESPACE::TQuaternion<DT>
operator+(DT d,
const ML_LA_NAMESPACE::TQuaternion<DT> &q){
961 return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw+d);
965 template <
typename DT>
966 inline ML_LA_NAMESPACE::TQuaternion<DT>
operator+(
const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
967 return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw+d);
971 template <
typename DT>
972 inline ML_LA_NAMESPACE::TQuaternion<DT>
operator+(
const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
973 const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
974 return qa.operator+(qb);
983 template <
typename DT>
984 inline ML_LA_NAMESPACE::TQuaternion<DT>
operator-(DT d,
const ML_LA_NAMESPACE::TQuaternion<DT> &q){
985 return ML_LA_NAMESPACE::TQuaternion<DT>(-q.qx, -q.qy, -q.qz, d-q.qw);
989 template <
typename DT>
990 inline ML_LA_NAMESPACE::TQuaternion<DT>
operator-(
const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
991 return ML_LA_NAMESPACE::TQuaternion<DT>(q.qx, q.qy, q.qz, q.qw-d);
995 template <
typename DT>
996 inline ML_LA_NAMESPACE::TQuaternion<DT>
operator-(
const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
997 const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
998 return qa.operator-(qb);
1003 template <
typename DT>
1004 inline ML_LA_NAMESPACE::TQuaternion<DT>
operator*(DT d,
const ML_LA_NAMESPACE::TQuaternion<DT> &q){
1009 template <
typename DT>
1010 inline ML_LA_NAMESPACE::TQuaternion<DT>
operator*(
const ML_LA_NAMESPACE::TQuaternion<DT> &q, DT d){
1015 template <
typename DT>
1016 inline ML_LA_NAMESPACE::TQuaternion<DT>
operator*(
const ML_LA_NAMESPACE::TQuaternion<DT> &qa,
1017 const ML_LA_NAMESPACE::TQuaternion<DT> &qb){
1018 return qa.operator*(qb);
1022 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1038 #ifdef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCTIONS
1039 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1040 ML_LA_START_NAMESPACE
1045 #ifdef _ML_IMPLEMENT_QUATERNION_SQRT
1046 template <
typename DT>
1047 inline ML_LA_NAMESPACE::TQuaternion<DT> sqrt (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.sqrt(); }
1051 template <
typename DT>
1052 inline ML_LA_NAMESPACE::TQuaternion<DT> exp (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.exp(); }
1055 template <
typename DT>
1056 inline ML_LA_NAMESPACE::TQuaternion<DT> ln (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.ln(); }
1059 template <
typename DT>
1060 inline ML_LA_NAMESPACE::TQuaternion<DT> sin (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.sin(); }
1063 template <
typename DT>
1064 inline ML_LA_NAMESPACE::TQuaternion<DT> cos (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.cos(); }
1067 template <
typename DT>
1068 inline ML_LA_NAMESPACE::TQuaternion<DT> tan (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.tan(); }
1071 template <
typename DT>
1072 inline ML_LA_NAMESPACE::TQuaternion<DT> cotan (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.cotan(); }
1075 template <
typename DT>
1076 inline ML_LA_NAMESPACE::TQuaternion<DT> sinh (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.sinh(); }
1079 template <
typename DT>
1080 inline ML_LA_NAMESPACE::TQuaternion<DT> cosh (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.cosh(); }
1083 template <
typename DT>
1084 inline ML_LA_NAMESPACE::TQuaternion<DT> tanh (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.tanh(); }
1087 template <
typename DT>
1088 inline ML_LA_NAMESPACE::TQuaternion<DT> cotanh (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.cotanh(); }
1091 template <
typename DT>
1092 inline ML_LA_NAMESPACE::TQuaternion<DT> arcsinh(
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arcsinh(); }
1095 template <
typename DT>
1096 inline ML_LA_NAMESPACE::TQuaternion<DT> arccosh(
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arccosh(); }
1099 template <
typename DT>
1100 inline ML_LA_NAMESPACE::TQuaternion<DT> arctanh(
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arctanh(); }
1103 template <
typename DT>
1104 inline ML_LA_NAMESPACE::TQuaternion<DT> arcsin (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arcsin(); }
1107 template <
typename DT>
1108 inline ML_LA_NAMESPACE::TQuaternion<DT> arccos (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arccos(); }
1111 template <
typename DT>
1112 inline ML_LA_NAMESPACE::TQuaternion<DT> arctan (
const ML_LA_NAMESPACE::TQuaternion<DT> &q) {
return q.arctan(); }
1115 #ifndef _ML_IMPLEMENT_GLOBAL_QUATERNION_FUNCS_AND_OPS_IN_GLOBAL_NAMESPACE
1129 template <
typename DT>
1130 inline ostream&
operator<<(ostream& s,
const ML_NAMESPACE::TQuaternion<DT> &v){
1131 return s <<
"(" << v.qx <<
"," << v.qy <<
"," << v.qz <<
"," << v.qw <<
")";
FloatingPointVector< T, 3, DataContainer > cross(const FloatingPointVector< T, 3, DataContainer > &b) const
Returns the cross product for elements, i.e., return vector vertical to *this and b.
T length() const
Returns the length of the vector, i.e. norm2().
T operator*(const FloatingPointVector< T, size, DataContainer > &a, const FloatingPointVector< T, size, DataContainer > &b)
Dot product, returns a.dot(b).
T dot(const FloatingPointVector< T, size, DataContainer > &buffer) const
Returns the dot product, i.e., sum of all components multiplied with corresponding components of buff...
FloatingPointVector< T, size, DataContainer > operator+(FloatingPointVector< T, size, DataContainer > lhs, const FloatingPointVector< T, size, DataContainer > &rhs)
Return value is the component wise addition of lhs and rhs.
FloatingPointVector< T, size, DataContainer > operator-(FloatingPointVector< T, size, DataContainer > lhs, const FloatingPointVector< T, size, DataContainer > &rhs)
Return value is the component wise subtraction of rhs from lhs.
Declaration of complex type traits:
TQuaternion(DT d)
Builds a quaternion from a scalar by setting all elements to 0 and qw to the scalar; use explicit to ...
DT dot(const TQuaternion< DT > &p) const
Dot product, equivalent to 4 component vector dot product.
TQuaternion< DT > add(const TQuaternion< DT > &b) const
Adds another quaternion to this one and returns the sum.
DT & operator[](const size_t i)
Indexing operator.
TQuaternion(DT x, DT y, DT z, DT w)
Creates a new TQuaternion with the DT values given.
DT qx
First element of imaginary part.
TQuaternion< DT > exp() const
Exponential and logarithmic functions: natural exponential, natural logarithm, power.
TQuaternion< DT > normalize(bool *isError=nullptr) const
Returns the normalization of the quaternion.
DT absoluteValue() const
Returns the absolute value of a quaternion which is the scalar quantity that determines the length of...
TQuaternion< DT > cotanh(bool *isError=nullptr) const
Computes the hyperbolic cotangent, for error handling see _ML_QUATERNION_CALC_CHECKED....
TQuaternion< DT > inverse(bool *isInvertible=nullptr) const
Computes and returns the inverse.
TQuaternion< DT > arctanh() const
Computes the inverse hyperbolic tangent.
TQuaternion< DT > div(const TQuaternion< DT > &d, bool *isError=nullptr) const
Divides a quaternion by another quaternion.
TQuaternion< DT > compDiv(const TQuaternion< DT > &b, bool *isError=nullptr) const
Divides each component by its corresponding component from b; the caller must guarantee that b does n...
TQuaternion< DT > sqrt(bool *isError=nullptr) const
Computes the square root of a quaternion.
void set(const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > &v, const DT w)
Sets all quaternion elements from a vector and DT parameter.
TQuaternion< DT > sinh() const
Hyperbolic functions: Hyperbolic sine, hyperbolic cosine, hyperbolic tangent Source: http://www....
TQuaternion< DT > tanh(bool *isError=nullptr) const
Computes the hyperbolic tangent, for error handling see _ML_QUATERNION_CALC_CHECKED....
TQuaternion< DT > cosh() const
Computes the hyperbolic cosine.
FloatingPointVector< DT, 3, Vector3DataContainer< DT > > & qv()
Returns a modifiable reference to the quaternion's imaginary part as vector object,...
TQuaternion< DT > conjugate() const
Computes the conjugate.
TQuaternion< DT > even(const TQuaternion< DT > &p) const
Even product, also known as Grassman inner product.
TQuaternion< DT > negate() const
Computes the negation.
TQuaternion< DT > euclideanMult(const TQuaternion< DT > &q) const
Euclidean product of this quaternion with another one (which is non-commutative).
TQuaternion< DT > arg(bool *isError=nullptr) const
Computes the quaternion argument.
TQuaternion< DT > arcsin(bool *isError=nullptr) const
Inverse trigonometric functions: Inverse sine, inverse cosine, inverse tangent.
DT norm() const
Computes the d norm.
TQuaternion< DT > mult(DT s) const
Multiplies this quaternion with a scalar factor.
TQuaternion()
Standard constructor, setting all elements to 0.
TQuaternion< DT > cos() const
Computes the cosine.
TQuaternion< DT > odd(const TQuaternion< DT > &p) const
Odd product, also known as cross-product or Grassman outer product.
DT value_type
Scalar type used for qx, qy, qz, and qw.
TQuaternion< DT > cotan(bool *isError=nullptr) const
Computes the cotangent, for error handling see _ML_QUATERNION_CALC_CHECKED.
TQuaternion< DT > tan(bool *isError=nullptr) const
Computes the tangent, for error handling see _ML_QUATERNION_CALC_CHECKED.
TQuaternion< DT > sin() const
Trigonometric functions: sine, cosine, tangent, cotangent.
TQuaternion< DT > outer(const TQuaternion< DT > &q) const
Euclidean outer product of this quaternion with another one.
void set(const DT x, const DT y, const DT z, const DT w)
Sets all quaternion elements qx, qy, qz, and qw from parameters x, y, z, and w, respectively.
TQuaternion< DT > mult(const TQuaternion< DT > &q) const
Multiplies this quaternion with another one (which is non-commutative). It is also called Grassman pr...
DT norm2() const
Computes the magnitude of the quaternion.
TQuaternion(const TQuaternion< DT2 > &q2)
Copy constructor from another TQuaternion of same or other type.
TQuaternion< DT > arcsinh() const
Inverse hyperbolic function: arcsinh, arccosh, arctanh.
TQuaternion< DT > ln() const
Computes the natural logarithm.
TQuaternion< DT > arctan(bool *isError=nullptr) const
Inverse tangent, for error handling see _ML_QUATERNION_CALC_CHECKED.
const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > & qv() const
Returns a constant reference to the quaternion's imaginary part as vector object.
DT qz
Third element of imaginary part.
Tmat4< DT > getAsMat4(bool *isConvertible=nullptr) const
Converts this quaternion to a 4x4 matrix.
TQuaternion(const FloatingPointVector< DT, 4 > &v)
Creates a new TQuaternion from the four-dimensional parameter vector.
TQuaternion< DT > pow(const TQuaternion< DT > &quat) const
Computes the power of a quaternion.
DT operator[](const size_t i) const
Constant indexing operator.
TQuaternion< DT > & operator=(const TQuaternion< DT > &q)
Assignment operator.
TQuaternion< DT > arccos(bool *isError=nullptr) const
Inverse cosine, for error handling see _ML_QUATERNION_CALC_CHECKED.
TQuaternion(const FloatingPointVector< DT, 3, Vector3DataContainer< DT > > &v, DT w)
Constructor with a vector and DT parameter.
TQuaternion< DT > sgn(bool *isError=nullptr) const
Returns the sign of the quaternion.
TQuaternion(const TQuaternion &q2)=default
explicitly generating the default constructor, to avoid a warning message with gcc9:
TQuaternion< DT > add(DT s) const
Adds a scalar to the quaternion and returns the sum, it is equivalent to a scalar add of s to the qw ...
FloatingPointVector< DT, 3, Vector3DataContainer< DT > > getImaginaryPart() const
Returns a copy of the quaternion's imaginary part.
TQuaternion< DT > arccosh() const
Computes the inverse hyperbolic cosine.
DT getRealPart() const
Returns a copy of the quaternion's real part, also called scalar() of a quaternion.
DT qy
Second element of imaginary part.
A four by four matrix class consisting of 4 row vectors.
void set(const DT val)
Sets all values to double val.
Forward declarations to resolve header file dependencies.
Specialized base class for the FloatingPointVectorDataContainerBase.
bool MLValueIs0WOM(MLint8 a)
Returns true if value is 0, otherwise false.
bool MLValuesAreEqualWOM(MLint8 a, MLint8 b)
Returns true if values a and b are equal, otherwise false.
#define ML_BAD_PARAMETER
A bad/invalid parameter (or even an inappropriate image) has been passed to a module or an algorithm;...
#define ML_CHECK_FLOAT(x)
MLEXPORT std::ostream & operator<<(std::ostream &s, const ml::Field &v)
Overloads the operator "<<" for stream output of Field objects.
#define _ML_QUAT_CALC_EXP
Internal helper macro - do not use.
#define _ML_QUATERNION_CALC_CHECKED(FUNC_NAME, CALC_EXPR)
Defines a code fragment which checks and handles some stuff for safe expression calculations.
ScopeGuard< Functor > operator+(ScopeGuardOnExit, Functor &&fn)
FloatingPointVector< T, size, DataContainer > operator/(FloatingPointVector< T, size, DataContainer > lhs, MLdouble rhs)
Component wise division of lhs by specialized rhs of type MLdouble.
void ML_UTILS_EXPORT printTemplateError(const char *location, MLErrorCode reason, const std::string_view &handling)
FloatingPointVector< T, size, DataContainer > & operator/=(FloatingPointVector< T, size, DataContainer > &op1, MLdouble value)
Arithmetic assignment: Component wise division of *this by scalar value.
TQuaternion< MLdouble > Quaternion
Define the default Quaternion type which is used by the ML; it uses double as component type.
FloatingPointVector< T, size, DataContainer > & operator-=(FloatingPointVector< T, size, DataContainer > &op1, const FloatingPointVector< T, size, DataContainer > &buffer)
Arithmetic assignment: Component wise subtraction of buffer from *this.
TQuaternion< MLfloat > Quaternionf
A smaller Quaternion type as specialization from TQuaternion.
bool operator==(const Tmat2< DT > &a, const Tmat2< DT > &b)
a == b ? Return true if yes.
T operator*(const FloatingPointVector< T, size, DataContainer > &a, const FloatingPointVector< T, size, DataContainer > &b)
Dot product, returns a.dot(b).
bool operator!=(const Tmat2< DT > &a, const Tmat2< DT > &b)
a != b ? Return true if yes.
TQuaternion< MLldouble > Quaternionld
A large Quaternion type for further extensions of the ML as specialization from TQuaternion.
TQuaternion< MLdouble > Quaterniond
The default Quaternion type used in the ML as specialization from TQuaternion.
FloatingPointVector< T, size, DataContainer > & operator+=(FloatingPointVector< T, size, DataContainer > &op1, const FloatingPointVector< T, size, DataContainer > &buffer)
Arithmetic assignment: Component wise addition.
FloatingPointVector< T, size, DataContainer > operator-(FloatingPointVector< T, size, DataContainer > lhs, const FloatingPointVector< T, size, DataContainer > &rhs)
Return value is the component wise subtraction of rhs from lhs.
FloatingPointVector< T, size, DataContainer > & operator*=(FloatingPointVector< T, size, DataContainer > &op1, MLdouble value)
Arithmetic assignment: Component wise multiplication *this with specialized MLdouble scalar value.