Skip to content

Commit

Permalink
Merge pull request #278 from Morpho-lang/dev
Browse files Browse the repository at this point in the history
v0.6.1 updated version
  • Loading branch information
softmattertheory authored Nov 18, 2024
2 parents 537e7b0 + 8fea848 commit f489eb0
Show file tree
Hide file tree
Showing 12 changed files with 205 additions and 36 deletions.
6 changes: 4 additions & 2 deletions src/classes/list.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,8 +224,10 @@ objectlist *list_concatenate(objectlist *a, objectlist *b) {
objectlist *new=object_newlist(a->val.count+b->val.count, NULL);

if (new) {
memcpy(new->val.data, a->val.data, sizeof(value)*a->val.count);
memcpy(new->val.data+a->val.count, b->val.data, sizeof(value)*b->val.count);
if (new->val.data) {
memcpy(new->val.data, a->val.data, sizeof(value)*a->val.count);
memcpy(new->val.data+a->val.count, b->val.data, sizeof(value)*b->val.count);
}
new->val.count=a->val.count+b->val.count;
}

Expand Down
1 change: 1 addition & 0 deletions src/classes/metafunction.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum {

void objectmetafunction_freefn(object *obj) {
objectmetafunction *f = (objectmetafunction *) obj;
morpho_freeobject(f->name);
varray_valueclear(&f->fns);
metafunction_clearinstructions(f);
}
Expand Down
24 changes: 12 additions & 12 deletions src/core/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -944,12 +944,6 @@ bool morpho_interpret(vm *v, value *rstart, instructionindx istart) {
a=DECODE_A(bc);
left=reg[a];
c=DECODE_B(bc); // We use c for consistency between call and invoke...

if (MORPHO_ISMETAFUNCTION(left) &&
!metafunction_resolve(MORPHO_GETMETAFUNCTION(left), c, reg+a+1, &v->err, &left)) {
ERRORCHK();
ERROR(VM_MLTPLDSPTCHFLD);
}

callfunction: // Jump here if an instruction becomes a call
if (MORPHO_ISINVOCATION(left)) {
Expand All @@ -958,6 +952,12 @@ bool morpho_interpret(vm *v, value *rstart, instructionindx istart) {
left=inv->method;
reg[a]=inv->receiver;
}

if (MORPHO_ISMETAFUNCTION(left) &&
!metafunction_resolve(MORPHO_GETMETAFUNCTION(left), c, reg+a+1, &v->err, &left)) {
ERRORCHK();
ERROR(VM_MLTPLDSPTCHFLD);
}

if (MORPHO_ISFUNCTION(left) || MORPHO_ISCLOSURE(left)) {
if (!vm_call(v, left, a, c, NULL, &pc, &reg)) goto vm_error;
Expand Down Expand Up @@ -1730,19 +1730,19 @@ bool morpho_call(vm *v, value f, int nargs, value *args, value *ret) {
value fn=f;
value r0=f;

if (MORPHO_ISMETAFUNCTION(fn) &&
!metafunction_resolve(MORPHO_GETMETAFUNCTION(fn), nargs, args, &v->err, &fn)) {
if (!morpho_checkerror(&v->err)) morpho_runtimeerror(v, VM_MLTPLDSPTCHFLD);
return false;
}

if (MORPHO_ISINVOCATION(fn)) {
/* An method invocation */
objectinvocation *inv = MORPHO_GETINVOCATION(f);
fn=inv->method;
r0=inv->receiver;
}

if (MORPHO_ISMETAFUNCTION(fn) &&
!metafunction_resolve(MORPHO_GETMETAFUNCTION(fn), nargs, args, &v->err, &fn)) {
if (!morpho_checkerror(&v->err)) morpho_runtimeerror(v, VM_MLTPLDSPTCHFLD);
return false;
}

if (MORPHO_ISBUILTINFUNCTION(fn)) {
objectbuiltinfunction *f = MORPHO_GETBUILTINFUNCTION(fn);

Expand Down
2 changes: 2 additions & 0 deletions src/datastructures/signature.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@ bool signature_parse(char *sig, signature *out) {
bool success=parse(&p);

parse_clear(&p);
lex_clear(&l);

return success;
}

Expand Down
89 changes: 69 additions & 20 deletions src/linalg/sparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -763,13 +763,17 @@ objectsparseerror sparse_docat(objectlist *in, void *dest, sparse_catcopyfn copy
objectsparseerror err = sparse_catcheckdimensions(in, ndim, dim, ncols, nrows);
if (err!=SPARSE_OK) return err;

if (!dest) { // If dest is NULL on entry, return the size of the matrix
if (!outrows || !outcols) return false;
*outrows=0; *outcols=0;
if (outrows) {
*outrows=0;
for (int i=0; i<dim[0]; i++) *outrows+=nrows[i];
}

if (outcols) {
*outcols=0;
for (int i=0; i<dim[1]; i++) *outcols+=ncols[i];
return true;
}

if (!dest) return SPARSE_OK;

int irow=0;

Expand All @@ -792,26 +796,26 @@ objectsparseerror sparse_docat(objectlist *in, void *dest, sparse_catcopyfn copy

/** Veneer onto sparse_docat for sparse matrices */
objectsparseerror sparse_cat(objectlist *in, objectsparse *dest) {
return sparse_docat(in, dest, sparse_catcopyentry, NULL, NULL);
return sparse_docat(in, dest, sparse_catcopyentry, &dest->dok.nrows, &dest->dok.ncols);
}

/** Veneer onto sparse_docat for dense matrices. Allocates a dense matrix of the correct size */
objectsparseerror sparse_catmatrix(objectlist *in, objectmatrix **out) {
int nrows, ncols;
objectmatrix *new = NULL;
objectsparseerror err=sparse_docat(in, NULL, matrix_catcopyentry, &nrows, &ncols);

if (!sparse_docat(in, NULL, matrix_catcopyentry, &nrows, &ncols)) goto sparse_catmatrix_error;
if (err!=SPARSE_OK) goto sparse_catmatrix_error;
new = object_newmatrix(nrows, ncols, true);

objectsparseerror err=sparse_docat(in, new, matrix_catcopyentry, NULL, NULL);

err=sparse_docat(in, new, matrix_catcopyentry, NULL, NULL);
if (err==SPARSE_OK) *out = new;

return err;

sparse_catmatrix_error:
if (new) object_free((object *) new);
return SPARSE_INVLDINIT;
return err;
}

/* *******************************
Expand Down Expand Up @@ -1037,8 +1041,6 @@ objectsparseerror sparse_mul(objectsparse *a, objectsparse *b, objectsparse *out
* @param[in] b - dense matrix
* @param[out] out - out + a*b. */
objectsparseerror sparse_mulsxd(objectsparse *a, objectmatrix *b, objectmatrix *out) {
if (!(sparse_checkformat(a, SPARSE_CCS, true, true))) return SPARSE_CONVFAILED;

if (a->ccs.ncols!=b->nrows) return SPARSE_INCMPTBLDIM;

#ifdef MORPHO_LINALG_USE_CSPARSE
Expand Down Expand Up @@ -1175,7 +1177,7 @@ void sparse_raiseerror(vm *v, objectsparseerror err) {
}
}

/** Constructs a Matrix object */
/** Constructs a Sparse object */
value sparse_constructor(vm *v, int nargs, value *args) {
int nrows, ncols;
objectsparse *new=NULL;
Expand Down Expand Up @@ -1356,14 +1358,16 @@ value Sparse_mul(vm *v, int nargs, value *args) {
morpho_resizeobject(v, (object *) b, bsize, sparse_size(b)); // Check for size change
} else morpho_runtimeerror(v, ERROR_ALLOCATIONFAILED);
} else if (MORPHO_ISMATRIX(MORPHO_GETARG(args, 0))) {
objectmatrix *b=MORPHO_GETMATRIX(MORPHO_GETARG(args, 0));

objectmatrix *out=object_newmatrix(b->nrows, b->ncols, true);
new = (objectsparse *) out; // Munge type to ensure binding/deallocation

if (out) {
err=sparse_mulsxd(a, b, out);
} else morpho_runtimeerror(v, ERROR_ALLOCATIONFAILED);
if (sparse_checkformat(a, SPARSE_CCS, true, true)) {
objectmatrix *b=MORPHO_GETMATRIX(MORPHO_GETARG(args, 0));

objectmatrix *out=object_newmatrix(a->ccs.nrows, b->ncols, true);
new = (objectsparse *) out; // Munge type to ensure binding/deallocation

if (out) {
err=sparse_mulsxd(a, b, out);
} else morpho_runtimeerror(v, ERROR_ALLOCATIONFAILED);
} else err=SPARSE_CONVFAILED;
} else if (MORPHO_ISNUMBER(MORPHO_GETARG(args, 0))) {
double scale;
if (!morpho_valuetofloat(MORPHO_GETARG(args, 0), &scale)) return MORPHO_NIL;
Expand Down Expand Up @@ -1521,6 +1525,50 @@ value Sparse_dimensions(vm *v, int nargs, value *args) {
return out;
}

/** Gets a column of a Sparse matrix */
value Sparse_getcolumn(vm *v, int nargs, value *args) {
value out = MORPHO_NIL;
objectsparse *s=MORPHO_GETSPARSE(MORPHO_SELF(args));

if (nargs==1 &&
MORPHO_ISINTEGER(MORPHO_GETARG(args, 0))) {
unsigned int col = MORPHO_GETINTEGERVALUE(MORPHO_GETARG(args, 0));

if (!sparse_checkformat(s, SPARSE_CCS, true, true)) {
morpho_runtimeerror(v, ERROR_ALLOCATIONFAILED);
return MORPHO_NIL;
}

if (col<s->ccs.ncols) {
int ncols=1, nentries=0, *entries=NULL;
double *values;
objectsparse *new=object_newsparse(&s->ccs.nrows, &ncols);

if (new) {
sparseccs_getrowindiceswithvalues(&s->ccs, col, &nentries, &entries, &values);

if (nentries>0) {
if (sparseccs_resize(&new->ccs, s->ccs.nrows, 1, nentries, true)) {
new->ccs.cptr[0]=0;
new->ccs.cptr[1]=nentries;

for (int i=0; i<nentries; i++) {
new->ccs.rix[i]=entries[i];
new->ccs.values[i]=values[i];
}
} else morpho_runtimeerror(v, ERROR_ALLOCATIONFAILED);
}

out=MORPHO_OBJECT(new);
morpho_bindobjects(v, 1, &out);

} else morpho_runtimeerror(v, ERROR_ALLOCATIONFAILED);
} else morpho_runtimeerror(v, MATRIX_INDICESOUTSIDEBOUNDS);
} else morpho_runtimeerror(v, MATRIX_SETCOLARGS);

return out;
}

/** Get the row indices given a column */
value Sparse_rowindices(vm *v, int nargs, value *args) {
objectsparse *s=MORPHO_GETSPARSE(MORPHO_SELF(args));
Expand Down Expand Up @@ -1656,6 +1704,7 @@ MORPHO_METHOD(MORPHO_COUNT_METHOD, Sparse_count, BUILTIN_FLAGSEMPTY),
MORPHO_METHOD(MATRIX_DIMENSIONS_METHOD, Sparse_dimensions, BUILTIN_FLAGSEMPTY),
MORPHO_METHOD(SPARSE_ROWINDICES_METHOD, Sparse_rowindices, BUILTIN_FLAGSEMPTY),
MORPHO_METHOD(SPARSE_SETROWINDICES_METHOD, Sparse_setrowindices, BUILTIN_FLAGSEMPTY),
MORPHO_METHOD(MATRIX_GETCOLUMN_METHOD, Sparse_getcolumn, BUILTIN_FLAGSEMPTY),
MORPHO_METHOD(SPARSE_COLINDICES_METHOD, Sparse_colindices, BUILTIN_FLAGSEMPTY),
MORPHO_METHOD(MORPHO_CLONE_METHOD, Sparse_clone, BUILTIN_FLAGSEMPTY),
MORPHO_METHOD(SPARSE_INDICES_METHOD, Sparse_indices, BUILTIN_FLAGSEMPTY)
Expand Down
4 changes: 4 additions & 0 deletions test/matrix/concatenate.morpho
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ print a
// expect: [ 0 1 ]
// expect: [ 1 0 ]

print b
// expect: [ 2 ]
// expect: [ 3 ]

var c = Matrix([[a, b], [b.transpose(), 0]])

print c
Expand Down
19 changes: 19 additions & 0 deletions test/sparse/block_constructor_dimensions.morpho
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Ensure a block contructor produces the correct matrix dimensions

var a = Sparse()

for (i in 0..4:2) {
a[i,i]=1
a[i+1,i]=2
a[i+3,i]=3
}

print Sparse([[a.column(0),a.column(1)]])
// expect: [ 1 0 ]
// expect: [ 2 0 ]
// expect: [ 0 0 ]
// expect: [ 3 0 ]
// expect: [ 0 0 ]
// expect: [ 0 0 ]
// expect: [ 0 0 ]
// expect: [ 0 0 ]
40 changes: 40 additions & 0 deletions test/sparse/column.morpho
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Sparse matrices

var a = Sparse()

for (i in 0..4:2) {
a[i,i]=1
a[i+1,i]=2
a[i+3,i]=3
}

print a.column(0)
// expect: [ 1 ]
// expect: [ 2 ]
// expect: [ 0 ]
// expect: [ 3 ]
// expect: [ 0 ]
// expect: [ 0 ]
// expect: [ 0 ]
// expect: [ 0 ]

print a.column(1)
// expect: [ 0 ]
// expect: [ 0 ]
// expect: [ 0 ]
// expect: [ 0 ]
// expect: [ 0 ]
// expect: [ 0 ]
// expect: [ 0 ]
// expect: [ 0 ]

print a.column(4)
// expect: [ 0 ]
// expect: [ 0 ]
// expect: [ 0 ]
// expect: [ 0 ]
// expect: [ 1 ]
// expect: [ 2 ]
// expect: [ 0 ]
// expect: [ 3 ]

4 changes: 2 additions & 2 deletions test/sparse/sparse_dense_mul.morpho
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ var B = Matrix([[1,2,3,4],[5,6,7,8]])
print B
// expect: [ 1 2 3 4 ]
// expect: [ 5 6 7 8 ]

print A*B.transpose()
// expect: [ 2 10 ]
// expect: [ 4 12 ]
// expect: [ 6 14 ]
// expect: [ 8 16 ]

print A*B.transpose()

print A*B
// expect error 'MtrxIncmptbl'
24 changes: 24 additions & 0 deletions test/sparse/sparse_dense_mul_dimensions.morpho
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//

var N = 3

var A = Sparse(2*N,N)
for (i in 0...N) {
A[i,i]=1
A[i+N,i]=1
}

var b = Matrix(List(1..N))

print A.dimensions() // expect: [ 6, 3 ]
print b.dimensions() // expect: [ 3, 1 ]

print (A*b).dimensions() // expect: [ 6, 1 ]

print A*b
// expect: [ 1 ]
// expect: [ 2 ]
// expect: [ 3 ]
// expect: [ 1 ]
// expect: [ 2 ]
// expect: [ 3 ]
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class A {
a() { return 0 }
a(x) { return 1 }
a(x, y) { return 2 }
a(x, y, z) { return 3 }
}

var a = A()
var b = a.a

print apply(b, []) // expect: 0
print apply(b, [1]) // expect: 1
print apply(b, [1,1]) // expect: 2
print apply(b, [1,1,1]) // expect: 3
14 changes: 14 additions & 0 deletions test/types/multiple_dispatch/invocation_multiple_dispatch.morpho
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class A {
a() { return 0 }
a(x) { return 1 }
a(x, y) { return 2 }
a(x, y, z) { return 3 }
}

var a = A()
var b = a.a

print b() // expect: 0
print b(1) // expect: 1
print b(1,1) // expect: 2
print b(1,1,1) // expect: 3

0 comments on commit f489eb0

Please sign in to comment.