Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libgap: add basic APIs for working with matrices #3554

Merged
merged 2 commits into from
Jul 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions src/libgap-api.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <signal.h>

#include "libgap-api.h"
#include "libgap_intern.h"

#include "ariths.h"
#include "bool.h"
Expand All @@ -27,6 +28,7 @@
#include "integer.h"
#include "lists.h"
#include "macfloat.h"
#include "modules.h"
#include "opers.h"
#include "plist.h"
#include "precord.h"
Expand Down Expand Up @@ -332,6 +334,59 @@ Obj GAP_NewPlist(Int capacity)
return NEW_PLIST(T_PLIST_EMPTY, capacity);
}


////
//// matrix obj
////

static Obj IsMatrixObjFilt;
static Obj NrRowsAttr;
static Obj NrColsAttr;

// Returns 1 if <obj> is a GAP matrix obj, 0 if not.
int GAP_IsMatrixObj(Obj obj)
{
return obj && DoFilter(IsMatrixObjFilt, obj) == True;
}

// Returns the number of rows of the given GAP matrix obj.
// If <mat> is not a GAP matrix obj, an error may be raised.
UInt GAP_NrRows(Obj mat)
{
Obj nrows = CALL_1ARGS(NrRowsAttr, mat);
return UInt_ObjInt(nrows);
}

// Returns the number of columns of the given GAP matrix obj.
// If <mat> is not a GAP matrix obj, an error may be raised.
UInt GAP_NrCols(Obj mat)
{
Obj ncols = CALL_1ARGS(NrColsAttr, mat);
return UInt_ObjInt(ncols);
}

// Assign <val> at position <pos> into the GAP matrix obj <mat>.
// If <val> is zero, then this unbinds the list entry.
// If <mat> is not a GAP matrix obj, an error may be raised.
void GAP_AssMat(Obj mat, UInt row, UInt col, Obj val)
{
Obj r = ObjInt_UInt(row);
Obj c = ObjInt_UInt(col);
ASS_MAT(mat, r, c, val);
}

// Returns the element at the <row>, <col> in the GAP matrix obj <mat>.
// Returns 0 if <row> or <col> are out of bounds, i.e., if either
// is zero, or larger than the number of rows respectively columns of the list.
// If <mat> is not a GAP matrix obj, an error may be raised.
Obj GAP_ElmMat(Obj mat, UInt row, UInt col)
{
Obj r = ObjInt_UInt(row);
Obj c = ObjInt_UInt(col);
return ELM_MAT(mat, r, c);
}


////
//// records
////
Expand Down Expand Up @@ -465,3 +520,34 @@ void GAP_Error_Postjmp_Returning_(void)
EnterStackCount = -EnterStackCount;
}
}


/****************************************************************************
**
*F InitKernel( <module> ) . . . . . . . . initialise kernel data structures
*/
static Int InitKernel(StructInitInfo * module)
{
ImportFuncFromLibrary("IsMatrixObj", &IsMatrixObjFilt);
ImportFuncFromLibrary("NrRows", &NrRowsAttr);
ImportFuncFromLibrary("NrCols", &NrColsAttr);

return 0;
}

/****************************************************************************
**
*F InitInfoLibGapApi() . . . . . . . . . . . . . . . table of init functions
*/
static StructInitInfo module = {
// init struct using C99 designated initializers; for a full list of
// fields, please refer to the definition of StructInitInfo
.type = MODULE_BUILTIN,
.name = "libgap",
.initKernel = InitKernel,
};

StructInitInfo * InitInfoLibGapApi ( void )
{
return &module;
}
29 changes: 28 additions & 1 deletion src/libgap-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ UInt GAP_LenList(Obj list);
// If <list> is not a GAP list, an error may be raised.
void GAP_AssList(Obj list, UInt pos, Obj val);

// Returns the element at the position <pos> in the list <list>.
// Returns the element at the position <pos> in the GAP list <list>.
// Returns 0 if there is no entry at the given position.
// Also returns 0 if <pos> is out of bounds, i.e., if <pos> is zero,
// or larger than the length of the list.
Expand All @@ -336,6 +336,33 @@ Obj GAP_ElmList(Obj list, UInt pos);
Obj GAP_NewPlist(Int capacity);


////
//// matrix obj
////

// Returns 1 if <obj> is a GAP matrix obj, 0 if not.
int GAP_IsMatrixObj(Obj obj);

// Returns the number of rows of the given GAP matrix obj.
// If <mat> is not a GAP matrix obj, an error may be raised.
UInt GAP_NrRows(Obj mat);

// Returns the number of columns of the given GAP matrix obj.
// If <mat> is not a GAP matrix obj, an error may be raised.
UInt GAP_NrCols(Obj mat);

// Assign <val> at position <pos> into the GAP matrix obj <mat>.
// If <val> is zero, then this unbinds the list entry.
// If <mat> is not a GAP matrix obj, an error may be raised.
void GAP_AssMat(Obj mat, UInt row, UInt col, Obj val);

// Returns the element at the <row>, <col> in the GAP matrix obj <mat>.
// Returns 0 if <row> or <col> are out of bounds, i.e., if either
// is zero, or larger than the number of rows respectively columns of the list.
// If <mat> is not a GAP matrix obj, an error may be raised.
Obj GAP_ElmMat(Obj mat, UInt row, UInt col);


////
//// records
////
Expand Down
29 changes: 29 additions & 0 deletions src/libgap_intern.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/****************************************************************************
**
** This file is part of GAP, a system for computational discrete algebra.
**
** Copyright of GAP belongs to its developers, whose names are too numerous
** to list here. Please refer to the COPYRIGHT file for details.
**
** SPDX-License-Identifier: GPL-2.0-or-later
*/

#ifndef LIBGAP_INTERN_H
#define LIBGAP_INTERN_H

#include "system.h"


/****************************************************************************
**
*F * * * * * * * * * * * * * initialize module * * * * * * * * * * * * * * *
*/

/****************************************************************************
**
*F InitInfoLibGapApi() . . . . . . . . . . . . . . . table of init functions
*/
StructInitInfo * InitInfoLibGapApi(void);


#endif // LIBGAP_INTERN_H
4 changes: 4 additions & 0 deletions src/modules_builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "info.h"
#include "intfuncs.h"
#include "iostream.h"
#include "libgap_intern.h"
#include "objccoll.h"
#include "objset.h"
#include "profile.h"
Expand Down Expand Up @@ -139,6 +140,9 @@ const InitInfoFunc InitFuncsBuiltinModules[] = {
InitInfoThreadAPI,
InitInfoAObjects,
InitInfoSerialize,
#else
// libgap API
InitInfoLibGapApi,
#endif

0
Expand Down
80 changes: 55 additions & 25 deletions tst/testlibgap/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
* TODO: Test error handling
*
*/

#include "common.h"

#include <intobj.h>


void records(void)
{
Expand All @@ -20,9 +23,9 @@ void records(void)
nam = GAP_MakeString("key");
val = GAP_MakeString("value");

assert(GAP_IsRecord(r) != 0);
assert(GAP_IsRecord(0) == 0);
assert(GAP_IsRecord(val) == 0);
assert(GAP_IsRecord(r));
assert(!GAP_IsRecord(0));
assert(!GAP_IsRecord(val));

GAP_AssRecord(r, nam, val);
ret = GAP_ElmRecord(r, nam);
Expand All @@ -40,9 +43,9 @@ void lists(void)
val = GAP_MakeString("value");
val2 = GAP_NewPrecord(5);

assert(GAP_IsList(r) != 0);
assert(GAP_IsList(0) == 0);
assert(GAP_IsList(val2) == 0);
assert(GAP_IsList(r));
assert(!GAP_IsList(0));
assert(!GAP_IsList(val2));

GAP_AssList(r, 1, val);
ret = GAP_ElmList(r, 1);
Expand All @@ -56,21 +59,44 @@ void lists(void)
assert(ret == 0);
}

void matrices(void)
{
Obj mat, val, row, ret;

mat = GAP_NewPlist(1);
val = INTOBJ_INT(42);

assert(!GAP_IsMatrixObj(mat)); // empty list, not yet a matrix
assert(!GAP_IsMatrixObj(0));
assert(!GAP_IsMatrixObj(val));

row = GAP_NewPlist(2);
GAP_AssList(row, 1, INTOBJ_INT(1));
GAP_AssList(row, 2, INTOBJ_INT(2));
GAP_AssList(mat, 1, row);
assert(!GAP_IsMatrixObj(row));
assert(GAP_IsMatrixObj(mat));

GAP_AssMat(mat, 1, 1, val);
ret = GAP_ElmMat(mat, 1, 1);
assert(ret == val);
}

void strings(void)
{
const char *ts = "Hello, world!";
Obj r, r2;

assert(GAP_IsString(0) == 0);
assert(!GAP_IsString(0));

r = GAP_MakeString(ts);
assert(GAP_LenString(r) == strlen(ts));
assert(GAP_IsString(r) != 0);
assert(GAP_IsString(r));
assert(strcmp(GAP_CSTR_STRING(r),ts) == 0);

r2 = GAP_MakeImmString(ts);
assert(GAP_LenString(r2) == strlen(ts));
assert(GAP_IsString(r2) != 0);
assert(GAP_IsString(r2));
assert(strcmp(GAP_CSTR_STRING(r2),ts) == 0);
}

Expand All @@ -79,21 +105,21 @@ void integers(void)
Obj i1,i2,o;

o = GAP_MakeString("test");
assert(GAP_IsInt(o) == 0);
assert(GAP_IsSmallInt(o) == 0);
assert(GAP_IsLargeInt(o) == 0);
assert(!GAP_IsInt(o));
assert(!GAP_IsSmallInt(o));
assert(!GAP_IsLargeInt(o));

const UInt limbs[1] = { 0 };
i1 = GAP_MakeObjInt(limbs, 1);
assert(GAP_IsInt(i1) != 0);
assert(GAP_IsSmallInt(i1) != 0);
assert(GAP_IsLargeInt(i1) == 0);
assert(GAP_IsInt(i1));
assert(GAP_IsSmallInt(i1));
assert(!GAP_IsLargeInt(i1));

const UInt limbs2[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
i2 = GAP_MakeObjInt(limbs2, -8);
assert(GAP_IsInt(i2) != 0);
assert(GAP_IsSmallInt(i2) == 0);
assert(GAP_IsLargeInt(i2) != 0);
assert(GAP_IsInt(i2));
assert(!GAP_IsSmallInt(i2));
assert(GAP_IsLargeInt(i2));
assert(GAP_SizeInt(i2) == -8);

assert(memcmp(GAP_AddrInt(i2), limbs2, sizeof(UInt) * 8) == 0);
Expand All @@ -112,15 +138,15 @@ void operations(void)
b = GAP_MakeObjInt(limbs2, -8);
l = GAP_NewPlist(2);

assert(GAP_EQ(a, a) != 0);
assert(GAP_EQ(a, b) == 0);
assert(GAP_EQ(a, a));
assert(!GAP_EQ(a, b));

assert(GAP_LT(a, b) == 0);
assert(GAP_LT(b, a) != 0);
assert(!GAP_LT(a, b));
assert(GAP_LT(b, a));

assert(GAP_IN(a, l) == 0);
assert(!GAP_IN(a, l));

assert(GAP_EQ(GAP_SUM(a, b), GAP_SUM(b,a)) != 0);
assert(GAP_EQ(GAP_SUM(a, b), GAP_SUM(b,a)));

// TODO: More sensible test than just executing?
// TODO: More objects?
Expand All @@ -145,7 +171,7 @@ void globalvars(void)

// Hopefully this always exists.
a = GAP_ValueGlobalVariable("GAPInfo");
assert(GAP_IsRecord(a) != 0);
assert(GAP_IsRecord(a));

x = GAP_CanAssignGlobalVariable("GAPInfo");
assert(x == 0);
Expand Down Expand Up @@ -175,6 +201,10 @@ int main(int argc, char ** argv)
lists();
printf("success\n");

printf("# Testing matrices... ");
matrices();
printf("success\n");

printf("# Testing integers... ");
integers();
printf("success\n");
Expand Down
1 change: 1 addition & 0 deletions tst/testlibgap/api.expect
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Testing strings... success
# Testing records... success
# Testing lists... success
# Testing matrices... success
# Testing integers... success
# Testing operations... success
# Testing global variables... success
Expand Down