---
name: "graphmat"
section: "3"
platform: "linux"
package: "libclippoly-dev"
version: "0.11-8"
release: "Debian 10 (Buster)"
platforms: ["linux"]
url: "https://new.carta.tech/graphmat"
---

# graphmat(3)

3d graphics and associated matrix and vector routines

## NAME

m\_alloc2, m\_free2, v\_alloc2, v\_free2, m\_alloc3, m\_free3, v\_alloc3, v\_free3, m\_cpy2, m\_unity2, v\_cpy2, v\_fill2, v\_unity2, v\_zero2, m\_cpy3, m\_unity3, v\_cpy3, v\_fill3, v\_unity3, v\_zero3, m\_det2, v\_len2, vtmv\_mul2, vv\_inprod2, m\_inv2, m\_tra2, mm\_add2, mm\_mul2, mm\_sub2, mtmm\_mul2, sm\_mul2, mv\_mul2, sv\_mul2, v\_homo2, v\_norm2, vv\_add2, vv\_sub2, vvt\_mul2, m\_det3, v\_len3, vtmv\_mul3, vv\_inprod3, m\_inv3, m\_tra3, mm\_add3, mm\_mul3, mm\_sub3, mtmm\_mul3, sm\_mul3, mv\_mul3, sv\_mul3, v\_homo3, v\_norm3, vv\_add3, vv\_cross3, vv\_sub3, vvt\_mul3, miraxis2, mirorig2, mirplane2, rot2, scaorig2, scaplane2, scaxis2, transl2, miraxis3, mirorig3, mirplane3, prjorthaxis, prjpersaxis, rot3, scaorig3, scaplane3, scaxis3, transl3 - 3d graphics and associated matrix and vector routines

```

```

## SYNOPSIS

```
#include <graphmat.h>
```

*/\* Data initialisation \*/*

**hmat2\_t \*m\_alloc2(m\_result)**\
 **hmat2\_t \*m\_result;**

**void m\_free2(matrix)**\
 **hmat2\_t \*matrix;**

**hvec2\_t \*v\_alloc2(v\_result)**\
 **hvec2\_t \*v\_result;**

**void v\_free2(vector)**\
 **hmat2\_t \*vector;**

**hmat3\_t \*m\_alloc3(m\_result)**\
 **hmat3\_t \*m\_result;**

**void m\_free3(matrix)**\
 **hmat3\_t \*matrix;**

**hvec3\_t \*v\_alloc3(v\_result)**\
 **hvec3\_t \*v\_result;**

**void v\_free3(vector)**\
 **hmat3\_t \*vector;**

**hmat2\_t \*m\_cpy2(m\_source, m\_result)**\
 **hmat2\_t \*m\_source, \*m\_result;**

**hmat2\_t \*m\_unity2( m\_result)**\
 **hmat2\_t \*m\_result;**

**hvec2\_t \*v\_cpy2(v\_source, v\_result)**\
 **hvec2\_t \*v\_source, \*v\_result;**

**hvec2\_t \*v\_fill2(x, y, w, v\_result)**\
 **double x, y, w;**\
 **hvec2\_t \*v\_result;**

**hvec2\_t \*v\_unity2(axis, v\_result)**\
 **b\_axis axis;**\
 **hvec2\_t \*v\_result;**

**hvec2\_t \*v\_zero2(v\_result)**\
 **hvec2\_t \*v\_result;**

**hmat3\_t \*m\_cpy3(m\_source, m\_result)**\
 **hmat3\_t \*m\_source, \*m\_result;**

**hmat3\_t \*m\_unity3(m\_result)**\
 **hmat3\_t \*m\_result;**

**hvec3\_t \*v\_cpy3(v\_source, v\_result)**\
 **hvec3\_t \*v\_source, \*v\_result;**

**hvec3\_t \*v\_fill3(x, y, z, w, v\_result)**\
 **double x, y, z, w;**\
 **hvec3\_t \*v\_result;**

**hvec3\_t \*v\_unity3(axis, v\_result)**\
 **b\_axis axis;**\
 **hvec3\_t \*v\_result;**

**hvec3\_t \*v\_zero3(vector)**\
 **hvec3\_t \*vector;**

*/\* Basic Linear Algebra \*/*

**double m\_det2(matrix)**\
 **hmat2\_t \*matrix;**

**double v\_len2(vector)**\
 **hvec2\_t \*vector;**

**double vtmv\_mul2(vector, matrix)**\
 **hvec2\_t \*vector;**\
 **hmat2\_t \*matrix;**

**double vv\_inprod2(vectorA, vectorB)**\
 **hvec2\_t \*vectorA, \*vectorB;**

**hmat2\_t \*m\_inv2(matrix, m\_result)**\
 **hmat2\_t \*matrix, \*m\_result;**

**hmat2\_t \*m\_tra2(matrix, m\_result)**\
 **hmat2\_t \*matrix, \*m\_result;**

**hmat2\_t \*mm\_add2(matrixA, matrixB, m\_result)**\
 **hmat2\_t \*matrixA, \*matrixB, \*m\_result;**

**hmat2\_t \*mm\_mul2(matrixA, matrixB, m\_result)**\
 **hmat2\_t \*matrixA, \*matrixB, \*m\_result;**

**hmat2\_t \*mm\_sub2(matrixA, matrixB, m\_result)**\
 **hmat2\_t \*matrixA, \*matrixB, \*m\_result;**

**hmat2\_t \*mtmm\_mul2(matrixA, matrixB, m\_result)**\
 **hmat2\_t \*matrixA, \*matrixB, \*m\_result;**

**hmat2\_t \*sm\_mul2(scalar, matrix, m\_result)**\
 **double scalar;**\
 **hmat2\_t \*matrix, \*m\_result;**

**hmat2\_t \*vvt\_mul2(vectorA, vectorB, m\_result)**\
 **hvec2\_t \*vectorA, \*vectorB;**\
 **hmat2\_t \*m\_result;**

**hvec2\_t \*mv\_mul2(matrix, vector, v\_result)**\
 **hmat2 \*matrix;**\
 **hvec2\_t \*vector, \*v\_result;**

**hvec2\_t \*sv\_mul2(scalar, vector, v\_result)**\
 **double scalar;**\
 **hvec2\_t \*vector, \*v\_result;**

**hvec2\_t \*v\_homo2(vector, v\_result)**\
 **hvec2\_t \*vector, \*v\_result;**

**hvec2\_t \*v\_norm2(vector, v\_result)**\
 **hvec2\_t \*vector, \*v\_result;**

**hvec2\_t \*vv\_add2(vectorA, vectorB, v\_result)**\
 **hvec2\_t \*vectorA, \*vectorB, \*v\_result;**

**hvec2\_t \*vv\_sub2(vectorA, vectorB, v\_result)**\
 **hvec2\_t \*vectorA, \*vectorB, \*v\_result;**

**double m\_det3(matrix)**\
 **hmat3\_t \*matrix;**

**double v\_len3(vector)**\
 **hvec3\_t \*vector;**

**double vtmv\_mul3(vector, matrix)**\
 **hvec3\_t \*vector;**\
 **hmat3\_t \*matrix;**

**double vv\_inprod3(vectorA, vectorB)**\
 **hvec3\_t \*vectorA, \*vectorB;**

**hmat3\_t \*m\_inv3(matrix, m\_result)**\
 **hmat3\_t \*matrix, \*m\_result;**

**hmat3\_t \*m\_tra3(matrix, m\_result)**\
 **hmat3\_t \*matrix, \*m\_result;**

**hmat3\_t \*mm\_add3(matrixA, matrixB, m\_result)**\
 **hmat3\_t \*matrixA, \*matrixB, \*m\_result;**

**hmat3\_t \*mm\_mul3(matrixA, matrixB, m\_result)**\
 **hmat3\_t \*matrixA, \*matrixB, \*m\_result;**

**hmat3\_t \*mm\_sub3(matrixA, matrixB, m\_result)**\
 **hmat3\_t \*matrixA, \*matrixB, \*m\_result;**

**hmat3\_t \*mtmm\_mul3(matrixA, matrixB, m\_result)**\
 **hmat3\_t \*matrixA, \*matrixB, \*m\_result;**

**hmat3\_t \*sm\_mul3(scalar, matrix, m\_result)**\
 **double scalar;**\
 **hmat3\_t \*matrix, \*m\_result;**

**hmat3\_t \*vvt\_mul3(vectorA, vectorB, m\_result)**\
 **hvec3\_t \*vectorA, \*vectorB;**\
 **hmat3\_t \*m\_result;**

**hvec3\_t \*mv\_mul3(matrix, vector, v\_result)**\
 **hmat3\_t \*matrix;**\
 **\*hvec3\_t \*vector, \*v\_result;**

**hvec3\_t \*sv\_mul3(scalar, vec, v\_result)**\
 **double scalar;**\
 **hvec3\_t \*vector, \*v\_result;**

**hvec3\_t \*v\_homo3(vector, v\_result)**\
 **hvec3\_t \*vector, \*v\_result;**

**hvec3\_t \*v\_norm3(vector, v\_result)**\
 **hvec3\_t \*vector, \*v\_result;**

**hvec3\_t \*vv\_add3(vectorA, vectorB, v\_result)**\
 **hvec3\_t \*vectorA, \*vectorB, \*v\_result;**

**hvec3\_t \*vv\_cross3(vectorA, vectorB, v\_result)**\
 **hvec3\_t \*vectorA, \*vectorB, \*v\_result;**

**hvec3\_t \*vv\_sub3(vectorA, vectorB, v\_result)**\
 **hvec3\_t \*vectorA, \*vectorB, \*v\_result;**

*/\* Elementary transformations \*/*

**hmat2\_t \*miraxis2(axis, m\_result)**\
 **b\_axis axis;**\
 **hmat2\_t \*m\_result;**

**hmat2\_t \*mirorig2(m\_result)**\
 **hmat2\_t \*m\_result;**

**hmat2\_t \*rot2( rotation, m\_result)**\
 **double rotation;**\
 **hmat2\_t \*m\_result;**

**hmat2\_t \*scaorig2(scale, m\_result)**\
 **double scale;**\
 **hmat2\_t \*m\_result;**

**hmat2\_t \*scaxis2(scale, axis, m\_result)**\
 **double scale;**\
 **b\_axis axis;**\
 **hmat2\_t \*m\_result;**

**hmat2\_t \*transl2(translation, m\_result)**\
 **hvec2\_t \*translation;**\
 **hmat2\_t \*m\_result;**

**hmat3\_t \*miraxis3(axis, m\_result)**\
 **b\_axis axis;**\
 **hmat3\_t \*m\_result;**

**hmat3\_t \*mirorig3(m\_result)**\
 **hmat3\_t \*m\_result;**

**hmat3\_t \*mirplane3(plane, m\_result)**\
 **b\_axis plane;**\
 **hmat3\_t \*m\_result;**

**hmat3\_t \*prjorthaxis(axis, m\_result)**\
 **b\_axis axis;**\
 **hmat3\_t \*m\_result;**

**hmat3\_t \*prjpersaxis(axis, m\_result)**\
 **b\_axis axis;**\
 **hmat3\_t \*m\_result;**

**hmat3\_t \*rot3( rotation, axis, m\_result)**\
 **double rotation;**\
 **b\_axis axis;**\
 **hmat3\_t \*m\_result;**

**hmat3\_t \*scaorig3(scale, m\_result)**\
 **double scale;**\
 **hmat3\_t \*m\_result;**

**hmat3\_t \*scaplane(scale, plane, m\_result)**\
 **double scale;**\
 **b\_axis plane;**\
 **hmat3\_t \*m\_result;**

**hmat3\_t \*scaxis3(scale, axis, m\_result)**\
 **double scale;**\
 **b\_axis axis;**\
 **hmat3\_t \*m\_result;**

**hmat3\_t \*transl3(translation, m\_result)**\
 **hvec3\_t \*translation;**\
 **hmat3\_t \*m\_result;**

## DESCRIPTION

Matrix and vector routines associated with 3d graphics in homogeneous coordinates, such as basic linear algebra and elementary transformations.

This library is setup with a multi-level approach.\
 *Level1 :* **the data level.**\
 *Level 2:* **the data initialisation level.**\
 *Level 3:* **basic linear algebra level.**\
 *Level 4:* **elementary transformation level.**\

*Level 1,* the data structures, is realised as follows :\
 **typedef union**\
 **{**\
 **double a\[3\];**\
 **struct**\
 **{**\
 **double x, y, w;**\
 **} s;**\
 **} hvec2\_t;**

**typedef union**\
 **{**\
 **double a\[4\];**\
 **struct**\
 **{**\
 **double x, y, z, w;**\
 **} s;**\
 **} hvec3\_t;**

**typedef struct**\
 **{**\
 **double m\[3\]\[3\];**\
 **} hmat2\_t;**

**typedef struct**\
 **{**\
 **double m\[4\]\[4\];**\
 **} hmat3\_t;**

To access the data elements of a vector or a matrix can be accessed with the macros:

\#define	v\_x( vec )		((vec).s.x)\
 \#define	v\_y( vec )		((vec).s.y)\
 \#define	v\_z( vec )		((vec).s.z)\
 \#define	v\_w( vec )		((vec).s.w)\
 \#define	v\_elem( vec, i )	((vec).a\[(i)\])\
 \#define	m\_elem( mat, i, j )	((mat).m\[(i)\]\[(j)\])\

**typedef enum**\
 **{**\
 **X\_AXIS, Y\_AXIS, Z\_AXIS**\
 **} b\_axis;**

The functions are as follows sorted:\
 first on the level in which they belong, then on their return value and then on their name.

## NAMES

The function names begin with an abbreviation of the type of operand, and in which order the operations will be carried out on that operand. Then the order of and which operation will be carried out, followed by the type of coordinates. (i.e *vtmv\_mul3(vector, matrix) :* first take the transpose of  *vector,* multiply the transpose with   *matrix,* this result is multiplied by the incoming vector, all coordinates are homogeneous 3d coordinates.)

## USAGE

All the "functions" may have been implemented as macro's, so you can't take the address of a function. It is however guaranteed that arguments  of each function/macro will be evaluated only once, except for the result argument, which can be evaluated multiple times.

All operations can be used in place, but overlapping data gives unspecified results.

If the parameter  *v\_result* or *m\_result* of a function or the parameter of an initialisation function equals **NULL,** space for the parameter will be dynamically allocated using  **malloc(),** otherwise the parameter is assumed to hold a pointer to a memory area which can be used. A pointer to the used area (which may have been new allocated) is always returned.\
 If an error occurred like memory could not be allocated, an attempt to divide by zero occurs, or an attempt to invert a singular matrix a general error-routine  will be called, which has two parameters : *gm\_errno* and  *gm\_func.*\
 *gm\_errno* is the error type which is one of the following constants :  **DIV0,** **NOMEM** or **MATSING.** *gm\_func* is a pointer to a string which contains the name of the function where the error occurred.

A pointer to the error routine is defined as follows :\
 **void (\* gm\_error)(gm\_errno, gm\_func);**\
 **gm\_error\_t gm\_errno;**\
 **char \*gm\_func;**

With  *gm\_error\_t* is defined as :\
 **typedef enum**\
 **{**\
 **DIV0, NOMEM, MATSING**\
 **} gm\_error\_t;**\

The default error handler will abort after printing a diagnostic. You can  redirect *gm\_error* to your own error handler. It is not advisable to return from the error handler as error recovery is not expected to take place.

Matrices are of type  **hmat3\_t** or  **hmat2\_t** for 2d or 3d coordinates, respectively. \
 Vectors are of type  **hvec3\_t** or  **hvec2\_t.**

The elements of a vector can be accessed in two manners, the first one is by name of an element of a structure, the second is like an array.

A plane is described by the normal to that plane, with the assumption made that the origin is an element of the plane.

*rotation* is assumed to be a radial.

If a function is deallocating memory, it will check if the incoming pointer is a **NULL** pointer.

*/\* Level2 : Data initialisation \*/*

**m\_alloc2(), v\_alloc2(), m\_alloc3(), v\_alloc3()** allocate memory for a data item of type  **hmat2\_t, hvec2\_t, hmat3\_t** and **hvec3\_t** respectively.\
 **m\_free2(), v\_free2(), m\_free3(), v\_free3()** reclaim the storage allocated previously. \
 **m\_cpy2(), m\_cpy3()** copies  *m\_matrix* into  *m\_result.*\
 **m\_unity2(), m\_unity3()** returns the unity matrix. (2d respectively 3d homogeneous coordinates)\
 **v\_cpy2(), v\_cpy3()** copies  *v\_source* into  *v\_result.* (2d respectively 3d homogeneous coordinates)\
 **v\_fill2(), v\_fill3()** fills  *v\_result* according the given values.\
 **v\_unity2(), v\_unity3()** returns the unity vector with  *w = 1.0,* the incoming basic axis  *axis = 1.0,* and the other element(s) are 0.0; (2d  respectively 3d homogeneous coordinates)\
 **v\_zero2(), v\_zero3()** return a vector with  *w* = 1.0 and the other elements 0.0;\
 **m\_cpy2(), m\_cpy3()** copies  *m\_source* into  *m\_result.* (2d respectively 3d homogeneous coordinates)

*/\* level3 : Basic Linear Algebra \*/*

**m\_det2(), m\_det3()** calculates the determinant of the incoming matrix. The determinant is calculated in cartesian rather than homogeneous coordinates.\
 **v\_len2(), v\_len3()** calculates the length of the cathesian part of the homogeneous vector.\
 **vtmv\_mul2(), vtmv\_mul3()** calculate the result of the transpose of the incoming vector multiplied by the incoming matrix multiplied by the incoming vector (2d respectively 3d homogeneous coordinates)\
 **vv\_inprod2(), vv\_inprod3()** calculates the geometrical innerproduct (vector . vector) of  *vectorA* and *vectorB.*\
 **m\_inv2(), m\_inv3()** calculates the inverse of  *matrix.* It is an error if the matrix in singular.\
 **m\_tra2(), m\_tra3()** calculates the transpose  *matrix.* (2d respectively 3d homogeneous coordinates)\
 **mm\_add2(), mm\_sub2(), mm\_add3(), mm\_sub3()** calculates the result of  *matrixA* + respectively - *matrixB.* This operation is unspecified in the sense of homogeneous coordinates; the matrices are taken in their normal, mathematial sense.\
 **mm\_mul2(), mm\_mul3()** calculates the result of  *matrixA\*matrixB* (2d respectively 3d homogeneous coordinates)\
 **mtmm\_mul2(), mtmm\_mul3()** calculates the result of the transpose of the incoming  *matrixA* multiplied by  *matrixB* multiplied by  *matrixA* (2d respectively 3d homogeneous coordinates)\
 **sm\_mul2(), sm\_mul3()** calculates the result of  *scalar\*matrix* (2d respectively 3d homogeneous coordinates)\
 **mv\_mul2(), mv\_mul3()** calculates the result of  *matrix\*vector* (2d respectively 3d homogeneous coordinates)\
 **sv\_mul2(), sv\_mul3()** calculates the result of  *scalar\*vector.* (2d respectively 3d homogeneous coordinates)\
 **v\_homo2(), v\_homo3()** homogenize  *vector* so that the  *w* component becomes 1.0 but the length of the vector in homogeneous coordinates stays the same. (2d respectively 3d homogeneous coordinates)\
 **v\_norm2(), v\_norm3()** normalises the incoming vector so the length of the cartesian vector becomes 1.0. The homogeneous length stays the same. (2d respectively 3d homogeneous coordinates)\
 **vv\_add2(), vv\_sub2(), vv\_add3(), vv\_sub3()** calculates the result of  *vectorA* + respectively - *vectorB.* These operations are done in the mathematical sense. Be careful with homogeneous coordinates, as not every possible input makes sense.\
 **vvt\_mul2(), vvt\_mul3()** calculates the result of  *vectorA* multiplied by the transpose of *vectorB* (2d respectively 3d homogeneous coordinates)\
 **vv\_cross3()** calculates the geometrical crossproduct ( *vectorA x vectorB) of two* vectors (3d homogeneous coordinates)

*/\* level4 : Elementary transformations \*/*

**miraxis2(), miraxis3()** calculates the mirror matrix with respect to  *axis.* (2d respectively 3d homogeneous coordinates)\
 **mirorg2(), mirorg3()** calculates the mirror matrix relative to the origin. (2d respectively 3d homogeneous coordinates)\
 **mirplane3()** calculates the mirror matrix relative to a plane. (3d homogeneous coordinates)\
 **rot2()** calculates the rotation matrix over  *rotation* relative to the origin. (2d homogeneous coordinates)\
 **rot3()** calculates the rotation matrix over  *rotation* along  *axis.* (3d homogeneous coordinates)\
 **scaorg2(), scaorg3()** calculates the matrix of scaling with *scale* relative to the origin. (2d respectively 3d homogeneous coordinates)\
 **scaplane3()** calculates the matrix of scaling with *scale* relative to a plane of which *plane* is the normal. (3d homogeneous coordinates)\
 **scaxis2(), scaxis3()** calculates the matrix of scaling with *scale* relative to the line given by *axis.* (2d respectively 3d homogeneous coordinates)\
 **transl2(), transl3()** calculates the translation matrix over  *translation.* (2d respectively 3d homogeneous coordinates)\
 **prjorthaxis()** calculates the orthographic projection matrix along  *axis.* (3d homogeneous coordinates)\
 **prjpersaxis()** calculates the perspective projection with along *axis* The focus is in the origin. The projection plane is on distance 1.0 before the camera. (3d homogeneous coordinates)

## CAVEATS

Vector addition and subtraction and matrix addition and subtraction are not defined for homogeneous coordinates. One can add and subtract a point vector and a free vector, but you have to normalise the point vector first. The result of the subtraction of two point vectors is a free vector.

Calculating the determinant of a matrix and the length of a vector is unspecified in the sense of homogeneous coordinates

## RETURN VALUES

There are six types of return values:  **void, double, \*hvec3\_t, \*hvec2\_t, \*hmat3\_t and \*hmat2\_t.**

## SEE ALSO

[graphadd(3)](/graphadd/3.md), [graphmat++(3)](/graphmat++/3.md), fmatpinv(3TV), malloc(3V), Graphics and matrix routines.

## NOTE

Library file is **/usr/local/lib/libgraphmat.a**

## AUTHOR

Hans Gringhuis.\
 Klamer Schutte
