/* (non-Javadoc)
@see org.joml.Quaternionfc#premul(org.joml.Quaternionfc, org.joml.Quaternionf)
494502
public Quaternionf premul(Quaternionfc q, Quaternionf dest) {
        dest.set(q.w() * x + q.x() * w + q.y() * z - q.z() * y,
                 q.w() * y - q.x() * z + q.y() * w + q.z() * x,
                 q.w() * z + q.x() * y - q.y() * x + q.z() * w,
                 q.w() * w - q.x() * x - q.y() * y - q.z() * z);
        return dest;
    }
1168901
public void rotate(Quaternion rotation, Point3D pivot1) {
		if (pivot1==null) {
			rotate(rotation);
		} else {
			Transform3D m = new Transform3D();
			m.setRotation(rotation);

			// Translate to the pivot
			this.getP1().setX(this.getP1().getX() - pivot1.getX());
			this.getP1().setY(this.getP1().getY() - pivot1.getY());
			this.getP1().setZ(this.getP1().getZ() - pivot1.getZ());

			m.transform(this.getP1());

			this.getP1().setX(this.getP1().getX() + pivot1.getX());
			this.getP1().setY(this.getP1().getY() + pivot1.getY());
			this.getP1().setZ(this.getP1().getZ() + pivot1.getZ());

			// Rotate the direction
			m.transform(this.getSegmentVector());
			this.getSegmentVector().normalize();
		}
	}
1250982
public Quaterniond div(Quaterniondc b, Quaterniond dest) {
        double invNorm = 1.0 / (b.x() * b.x() + b.y() * b.y() + b.z() * b.z() + b.w() * b.w());
        double x = -b.x() * invNorm;
        double y = -b.y() * invNorm;
        double z = -b.z() * invNorm;
        double w = b.w() * invNorm;
        dest.set(this.w * x + this.x * w + this.y * z - this.z * y,
                 this.w * y - this.x * z + this.y * w + this.z * x,
                 this.w * z + this.x * y - this.y * x + this.z * w,
                 this.w * w - this.x * x - this.y * y - this.z * z);
        return dest;
    }
1070239
public Quaternionf normalize(Quaternionf dest) {
        float invNorm = (float) (1.0 / Math.sqrt(x * x + y * y + z * z + w * w));
        dest.x = x * invNorm;
        dest.y = y * invNorm;
        dest.z = z * invNorm;
        dest.w = w * invNorm;
        return dest;
    }
920407
public Quaternionf nlerpIterative(Quaternionfc q, float alpha, float dotThreshold, Quaternionf dest) {
        float q1x = x, q1y = y, q1z = z, q1w = w;
        float q2x = q.x(), q2y = q.y(), q2z = q.z(), q2w = q.w();
        float dot = q1x * q2x + q1y * q2y + q1z * q2z + q1w * q2w;
        float absDot = Math.abs(dot);
        if (1.0f - 1E-6f < absDot) {
            return dest.set(this);
        }
        float alphaN = alpha;
        while (absDot < dotThreshold) {
            float scale0 = 0.5f;
            float scale1 = dot >= 0.0f ? 0.5f : -0.5f;
            if (alphaN < 0.5f) {
                q2x = scale0 * q2x + scale1 * q1x;
                q2y = scale0 * q2y + scale1 * q1y;
                q2z = scale0 * q2z + scale1 * q1z;
                q2w = scale0 * q2w + scale1 * q1w;
                float s = (float) (1.0 / Math.sqrt(q2x * q2x + q2y * q2y + q2z * q2z + q2w * q2w));
                q2x *= s;
                q2y *= s;
                q2z *= s;
                q2w *= s;
                alphaN = alphaN + alphaN;
            } else {
                q1x = scale0 * q1x + scale1 * q2x;
                q1y = scale0 * q1y + scale1 * q2y;
                q1z = scale0 * q1z + scale1 * q2z;
                q1w = scale0 * q1w + scale1 * q2w;
                float s = (float) (1.0 / Math.sqrt(q1x * q1x + q1y * q1y + q1z * q1z + q1w * q1w));
                q1x *= s;
                q1y *= s;
                q1z *= s;
                q1w *= s;
                alphaN = alphaN + alphaN - 1.0f;
            }
            dot = q1x * q2x + q1y * q2y + q1z * q2z + q1w * q2w;
            absDot = Math.abs(dot);
        }
        float scale0 = 1.0f - alphaN;
        float scale1 = dot >= 0.0f ? alphaN : -alphaN;
        float resX = scale0 * q1x + scale1 * q2x;
        float resY = scale0 * q1y + scale1 * q2y;
        float resZ = scale0 * q1z + scale1 * q2z;
        float resW = scale0 * q1w + scale1 * q2w;
        float s = (float) (1.0 / Math.sqrt(resX * resX + resY * resY + resZ * resZ + resW * resW));
        dest.x = resX * s;
        dest.y = resY * s;
        dest.z = resZ * s;
        dest.w = resW * s;
        return dest;
    }
1230525
public Quaterniond add(double x, double y, double z, double w) {
        return add(x, y, z, w, this);
    }
486361
public void rotate(Quaternion rotation, Point3D pivot1) {
		if (pivot1==null) {
			rotate(rotation);
		} else {
			assert(pivot1!=null);

			Transform3D tr = new Transform3D();
			tr.setRotation(rotation);
			Vector3f v = new Vector3f();

			v.sub(this.getP1(), pivot1);
			tr.transform(v);
			this.getP1().add(pivot1, v);

			v.sub(this.getP2(), pivot1);
			tr.transform(v);
			this.getP2().add(pivot1, v);

			v.sub(this.getP3(), pivot1);
			tr.transform(v);
			this.getP3().add(pivot1, v);

			clearBufferedData();
		}
	}
509059
public Quaterniond nlerpIterative(Quaterniondc q, double alpha, double dotThreshold, Quaterniond dest) {
        double q1x = x, q1y = y, q1z = z, q1w = w;
        double q2x = q.x(), q2y = q.y(), q2z = q.z(), q2w = q.w();
        double dot = q1x * q2x + q1y * q2y + q1z * q2z + q1w * q2w;
        double absDot = Math.abs(dot);
        if (1.0 - 1E-6 < absDot) {
            return dest.set(this);
        }
        double alphaN = alpha;
        while (absDot < dotThreshold) {
            double scale0 = 0.5;
            double scale1 = dot >= 0.0 ? 0.5 : -0.5;
            if (alphaN < 0.5) {
                q2x = scale0 * q2x + scale1 * q1x;
                q2y = scale0 * q2y + scale1 * q1y;
                q2z = scale0 * q2z + scale1 * q1z;
                q2w = scale0 * q2w + scale1 * q1w;
                double s = 1.0 / Math.sqrt(q2x * q2x + q2y * q2y + q2z * q2z + q2w * q2w);
                q2x *= s;
                q2y *= s;
                q2z *= s;
                q2w *= s;
                alphaN = alphaN + alphaN;
            } else {
                q1x = scale0 * q1x + scale1 * q2x;
                q1y = scale0 * q1y + scale1 * q2y;
                q1z = scale0 * q1z + scale1 * q2z;
                q1w = scale0 * q1w + scale1 * q2w;
                double s = 1.0 / Math.sqrt(q1x * q1x + q1y * q1y + q1z * q1z + q1w * q1w);
                q1x *= s;
                q1y *= s;
                q1z *= s;
                q1w *= s;
                alphaN = alphaN + alphaN - 1.0;
            }
            dot = q1x * q2x + q1y * q2y + q1z * q2z + q1w * q2w;
            absDot = Math.abs(dot);
        }
        double scale0 = 1.0 - alphaN;
        double scale1 = dot >= 0.0 ? alphaN : -alphaN;
        double destX = scale0 * q1x + scale1 * q2x;
        double destY = scale0 * q1y + scale1 * q2y;
        double destZ = scale0 * q1z + scale1 * q2z;
        double destW = scale0 * q1w + scale1 * q2w;
        double s = 1.0 / Math.sqrt(destX * destX + destY * destY + destZ * destZ + destW * destW);
        dest.x *= s;
        dest.y *= s;
        dest.z *= s;
        dest.w *= s;
        return dest;
    }
652902
@Override
	public String getDefaultOrientation() {
		StringBuilder s = new StringBuilder();
		s.append(setCentroid());

		// calculate  orientation
		Quat4d q = new Quat4d();
		q.set(polyhedron.getViewMatrix(0));
		q.normalize();
		Quat4d r = new Quat4d();
		r.set(rotationAxisAligner.getRotationMatrix());
		r.normalize();
		q.mul(r);
		q.normalize();

		// set orientation
		s.append("moveto 0 quaternion{");
		s.append(jMolFloat(q.x));
		s.append(",");
		s.append(jMolFloat(q.y));
		s.append(",");
		s.append(jMolFloat(q.z));
		s.append(",");
		s.append(jMolFloat(q.w));
		s.append("};");
		return s.toString();
	}
413731
public void setFundamental( DMatrixRMaj F , Point3D_F64 e2 ) {
		if( e2 != null )
			this.e2.set(e2);
		else {
			MultiViewOps.extractEpipoles(F,new Point3D_F64(),this.e2);
		}
		GeometryMath_F64.multCrossA(this.e2,F,A);
	}
215319
function _constructPre(f, pre) {
    return function _wrapped() {
        pre.apply(this, arguments);
        return f.apply(this, arguments);
    };
}
492280
public Quaternionf ConvertDirectionalVectorToQuaternion(Vector3f d) {
        d.negate();
        Quaternionf q = new Quaternionf();
        // check for exception condition
        if ((d.x == 0) && (d.z == 0)) {
            // exception condition if direction is (0,y,0):
            // straight up, straight down or all zero's.
            if (d.y > 0) { // direction straight up
                AxisAngle4f angleAxis = new AxisAngle4f(-(float) Math.PI / 2, 1, 0,
                        0);
                q.set(angleAxis);
            } else if (d.y < 0) { // direction straight down
                AxisAngle4f angleAxis = new AxisAngle4f((float) Math.PI / 2, 1, 0, 0);
                q.set(angleAxis);
            } else { // All zero's. Just set to identity quaternion
                q.identity();
            }
        } else {
            d.normalize();
            Vector3f up = new Vector3f(0, 1, 0);
            Vector3f s = new Vector3f();
            d.cross(up, s);
            s.normalize();
            Vector3f u = new Vector3f();
            d.cross(s, u);
            u.normalize();
            Matrix4f matrix = new Matrix4f(s.x, s.y, s.z, 0, u.x, u.y, u.z, 0, d.x,
                    d.y, d.z, 0, 0, 0, 0, 1);
            q.setFromNormalized(matrix);
        }
        return q;
    }
101330
public void equiToNorm(float x , float y , Point3D_F32 norm ) {
		equiToLatLon(x,y, temp);
		ConvertCoordinates3D_F32.latlonToUnitVector(temp.lat,temp.lon, norm);
	}
75877
public Quaternion fromVectorFromNegativeZ (double tx, double ty, double tz) {
        double angle = Math.acos(-tz);
        if (angle < MathUtil.EPSILON) {
            return set(IDENTITY);
        }
        if (angle > Math.PI - MathUtil.EPSILON) {
            return set(0f, 1f, 0f, 0f); // 180 degrees about y
        }
        double len = Math.hypot(tx, ty);
        return fromAngleAxis(angle, ty/len, -tx/len, 0f);
    }
388388
public void setRotation(Quaternionf rotation) {
        setRotation(rotation.w, rotation.x, rotation.y,
                rotation.z);
    }
1318570
public final void mul(Quaternion q1) {
		double x1, y1, w1; 

		w1 = this.w*q1.w - this.x*q1.x - this.y*q1.y - this.z*q1.z;
		x1 = this.w*q1.x + q1.w*this.x + this.y*q1.z - this.z*q1.y;
		y1 = this.w*q1.y + q1.w*this.y - this.x*q1.z + this.z*q1.x;
		this.z = this.w*q1.z + q1.w*this.z + this.x*q1.y - this.y*q1.x;
		this.w = w1;
		this.x = x1;
		this.y = y1;
	}
1006392
@Override
    public Quaternionf wrapQuaternion(ByteBuffer buffer, int offset) {
    	float w = buffer.getFloat(offset);
    	float x = buffer.getFloat(offset + 4);
    	float y = buffer.getFloat(offset + 8);
    	float z = buffer.getFloat(offset + 12);
        return new Quaternionf(x, y, z, w);
    }