#pragma once
/*
 *  $Id: xyz.h 30135 2026-06-25 09:43:04Z yeti-dn $
 *  Copyright (C) 2025-2026 David Necas (Yeti).
 *  E-mail: yeti@gwyddion.net.
 *
 *  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
 *  License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any
 *  later version.
 *
 *  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 *  details.
 *
 *  You should have received a copy of the GNU General Public License along with this program; if not, write to the
 *  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#ifndef __GWY_XYZ_H__
#define __GWY_XYZ_H__

#include <math.h>
#include <glib.h>
#include <glib-object.h>

G_BEGIN_DECLS

typedef struct {
    gdouble x;
    gdouble y;
    gdouble z;
} GwyXYZ;

#define GWY_TYPE_XYZ (gwy_xyz_get_type())

GType   gwy_xyz_get_type (void)                 G_GNUC_CONST;
GwyXYZ* gwy_xyz_new      (gdouble x,
                          gdouble y,
                          gdouble z)            G_GNUC_MALLOC;
GwyXYZ* gwy_xyz_copy     (const GwyXYZ *xyz)    G_GNUC_MALLOC;
void    gwy_xyz_free     (GwyXYZ *xyz);
gdouble gwy_xyz_len      (const GwyXYZ *xyz);
gdouble gwy_xyz_len2     (const GwyXYZ *xyz);
gdouble gwy_xyz_dist2    (const GwyXYZ *xyz,
                          const GwyXYZ *other);
gdouble gwy_xyz_dotprod  (const GwyXYZ *xyz,
                          const GwyXYZ *other);
void    gwy_xyz_crossprod(const GwyXYZ *xyz,
                          const GwyXYZ *other,
                          GwyXYZ *result);

/* See math.h for an extensive discussion of the inline function definition scheme. */
#ifndef __GI_SCANNER__
#ifndef __GTK_DOC_IGNORE__
#define gwy_xyz_len       _gwy_xyz_len_implementation
#define gwy_xyz_len2      _gwy_xyz_len2_implementation
#define gwy_xyz_dist2     _gwy_xyz_dist2_implementation
#define gwy_xyz_dotprod   _gwy_xyz_dotprod_implementation
#define gwy_xyz_crossprod _gwy_xyz_crossprod_implementation

G_GNUC_UNUSED
static inline gdouble
_gwy_xyz_len_implementation(const GwyXYZ *xyz)
{
    return sqrt(xyz->x*xyz->x + xyz->y*xyz->y + xyz->z*xyz->z);
}

G_GNUC_UNUSED
static inline gdouble
_gwy_xyz_len2_implementation(const GwyXYZ *xyz)
{
    return xyz->x*xyz->x + xyz->y*xyz->y + xyz->z*xyz->z;
}

G_GNUC_UNUSED
static inline gdouble
_gwy_xyz_dist2_implementation(const GwyXYZ *xyz, const GwyXYZ *other)
{
    return (xyz->x - other->x)*(xyz->x - other->x)
            + (xyz->y - other->y)*(xyz->y - other->y)
            + (xyz->z - other->z)*(xyz->z - other->z);
}

G_GNUC_UNUSED
static inline gdouble
_gwy_xyz_dotprod_implementation(const GwyXYZ *xyz, const GwyXYZ *other)
{
    return xyz->x*other->x + xyz->y*other->y + xyz->z*other->z;
}

G_GNUC_UNUSED
static inline void
_gwy_xyz_crossprod_implementation(const GwyXYZ *xyz, const GwyXYZ *other, GwyXYZ *result)
{
    gdouble x = xyz->y*other->z - xyz->z*other->y;
    gdouble y = xyz->z*other->x - xyz->x*other->z;
    gdouble z = xyz->x*other->y - xyz->y*other->x;
    result->x = x;
    result->y = y;
    result->z = z;
}

#endif
#endif

G_END_DECLS

#endif

/* vim: set cin columns=120 tw=118 et ts=4 sw=4 cino=>1s,e0,n0,f0,{0,}0,^0,\:1s,=0,g1s,h0,t0,+1s,c3,(0,u0 : */
