/*
* Copyright (c) 2005-2008 Hypertriton, Inc.
*
* 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 OR CONTRIBUTORS 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.
*/
/*
* Utility and I/O routines for math library.
*/
#include
#include
#include
#include "m.h"
#ifdef ENABLE_GUI
# include
# include
# include "m_plotter.h"
# include "m_matview.h"
#endif
#ifdef ENABLE_GUI
/*
* Math library extensions to AG_Label(3).
*/
static void
PrintReal(AG_Label *lbl, char *s, size_t len, int fPos)
{
M_Real r = AG_LABEL_ARG(lbl,M_Real);
#if defined(QUAD_PRECISION)
Snprintf(s, len, "%llf", r);
#else
Snprintf(s, len, "%f", r);
#endif
}
static void
PrintTime(AG_Label *lbl, char *s, size_t len, int fPos)
{
M_Time t = AG_LABEL_ARG(lbl,M_Time);
AG_UnitFormat((double)t, agTimeUnits, s, len);
}
static void
PrintComplex(AG_Label *lbl, char *s, size_t len, int fPos)
{
M_Complex *c = AG_LABEL_ARG(lbl,M_Complex *);
Snprintf(s, len, "%f+%fi", c->r, c->i);
}
static void
PrintVector(AG_Label *lbl, char *s, size_t len, int fPos)
{
char num[16];
M_Vector *v = AG_LABEL_ARG(lbl,M_Vector *);
Uint i;
s[0] = '[';
s[1] = '\0';
for (i = 0; i < v->m; i++) {
M_Real *e = M_VecGetElement(v,i);
Snprintf(num, sizeof(num), "%.2g", *e);
Strlcat(s, num, len);
if (i < v->m-1) { Strlcat(s, "; ", len); }
}
Strlcat(s, "]", len);
}
static void
PrintMatrix(AG_Label *lbl, char *s, size_t len, int fPos)
{
char num[16];
M_Matrix *M = AG_LABEL_ARG(lbl,M_Matrix *);
Uint i, j;
s[0] = '[';
s[1] = '\0';
for (i = 0; i < M->m; i++) {
for (j = 0; j < M->n; j++) {
M_Real *e = M_GetElement(M,i,j);
Snprintf(num, sizeof(num), "%.2g", *e);
Strlcat(s, num, len);
if (j < M->n-1) { Strlcat(s, ", ", len); }
}
if (i < M->m-1) { Strlcat(s, "; ", len); }
}
Strlcat(s, "]", len);
}
#endif /* ENABLE_GUI */
/* Initialize the math library. */
void
M_InitSubsystem(void)
{
M_VectorInitEngine();
M_MatrixInitEngine();
#ifdef ENABLE_GUI
if (agGUI) {
AG_RegisterClass(&mPlotterClass);
AG_RegisterClass(&mMatviewClass);
AG_RegisterLabelFormat("R", PrintReal);
AG_RegisterLabelFormat("T", PrintTime);
AG_RegisterLabelFormat("C", PrintComplex);
AG_RegisterLabelFormat("V", PrintVector);
AG_RegisterLabelFormat("M", PrintMatrix);
}
#endif /* ENABLE_GUI */
}
/* Release resources allocated by the math library. */
void
M_DestroySubsystem(void)
{
}
/* Unserialize a real number. */
M_Real
M_ReadReal(AG_DataSource *ds)
{
Uint8 prec;
prec = AG_ReadUint8(ds);
switch (prec) {
case 1:
return ((M_Real)AG_ReadFloat(ds));
case 2:
return ((M_Real)AG_ReadDouble(ds));
case 4:
#ifdef HAVE_LONG_DOUBLE
return ((M_Real)AG_ReadLongDouble(ds));
#else
/* XXX TODO convert */
#endif
default:
AG_FatalError("Cannot convert real (%d)", (int)prec);
}
return (0.0);
}
/* Unserialize a real number (pointer variant). */
void
M_CopyReal(AG_DataSource *ds, M_Real *rv)
{
Uint8 prec;
prec = AG_ReadUint8(ds);
switch (prec) {
case 1:
*rv = (M_Real)AG_ReadFloat(ds);
break;
case 2:
*rv = (M_Real)AG_ReadDouble(ds);
break;
case 4:
#ifdef HAVE_LONG_DOUBLE
*rv = (M_Real)AG_ReadLongDouble(ds);
#else
/* XXX TODO convert */
#endif
break;
default:
AG_FatalError("Cannot convert real (%d)", (int)prec);
}
}
/* Serialize a real number. */
void
M_WriteReal(AG_DataSource *ds, M_Real v)
{
#if defined(QUAD_PRECISION)
AG_WriteUint8(ds, 4);
AG_WriteLongDouble(ds, (long double)v);
#elif defined(DOUBLE_PRECISION)
AG_WriteUint8(ds, 2);
AG_WriteDouble(ds, (double)v);
#else
AG_WriteUint8(ds, 1);
AG_WriteFloat(ds, (float)v);
#endif
}
/* Unserialize a complex number. */
M_Complex
M_ReadComplex(AG_DataSource *ds)
{
M_Complex v;
v.r = M_ReadReal(ds);
v.i = M_ReadReal(ds);
return (v);
}
/* Unserialize a complex number (pointer variant). */
void
M_CopyComplex(AG_DataSource *ds, M_Complex *v)
{
v->r = M_ReadReal(ds);
v->i = M_ReadReal(ds);
}
/* Serialize a complex number. */
void
M_WriteComplex(AG_DataSource *ds, M_Complex v)
{
M_WriteReal(ds, v.r);
M_WriteReal(ds, v.i);
}
/* Unserialize a range value. */
M_Range
M_ReadRange(AG_DataSource *ds)
{
M_Range r;
r.min = M_ReadReal(ds);
r.typ = M_ReadReal(ds);
r.max = M_ReadReal(ds);
return (r);
}
/* Unserialize a range value (pointer variant). */
void
M_CopyRange(AG_DataSource *ds, M_Range *r)
{
r->min = M_ReadReal(ds);
r->typ = M_ReadReal(ds);
r->max = M_ReadReal(ds);
}
/* Serialize a range value. */
void
M_WriteRange(AG_DataSource *ds, M_Range r)
{
M_WriteReal(ds, r.min);
M_WriteReal(ds, r.typ);
M_WriteReal(ds, r.max);
}
/* Unserialize a time range value. */
M_TimeRange
M_ReadTimeRange(AG_DataSource *ds)
{
M_TimeRange r;
r.min = M_ReadTime(ds);
r.typ = M_ReadTime(ds);
r.max = M_ReadTime(ds);
return (r);
}
/* Unserialize a time range value (pointer variant). */
void
M_CopyTimeRange(AG_DataSource *ds, M_TimeRange *r)
{
r->min = M_ReadTime(ds);
r->typ = M_ReadTime(ds);
r->max = M_ReadTime(ds);
}
/* Serialize a time range value. */
void
M_WriteTimeRange(AG_DataSource *ds, M_TimeRange r)
{
M_WriteTime(ds, r.min);
M_WriteTime(ds, r.typ);
M_WriteTime(ds, r.max);
}