ref: ecef9816dc8f772ca7f93cfcfe914759065e358f
dir: /array.c/
#include <u.h> #include <libc.h> #include <thread.h> #include "dat.h" #include "fns.h" /* This file is the only file that knows how arrays are stored. * In theory, that allows us to experiment with other representations later. */ struct Array { int type; int rank; usize size; usize *shape; union { void *data; vlong *intdata; Rune *chardata; Array **arraydata; }; }; void initarrays(void) { dataspecs[DataArray].size = sizeof(Array); } Array * allocarray(int type, int rank, usize size) { Array *a = alloc(DataArray); a->type = type; a->rank = rank; a->size = size; switch(type){ case TypeNumber: size *= sizeof(vlong); break; case TypeChar: size *= sizeof(Rune); break; case TypeArray: size *= sizeof(Array *); break; } a->shape = allocextra(a, (sizeof(usize) * rank) + size); a->data = (void*)(a->shape+rank); return a; } void setint(Array *a, usize offset, vlong v) { a->intdata[offset] = v; } void setarray(Array *a, usize offset, Array *v) { a->arraydata[offset] = v; } void setshape(Array *a, int dim, usize size) { a->shape[dim] = size; } static int printarraysub(char *, Array *, int); static int printitem(char *p, Array *a, uvlong i, int depth) { switch(a->type){ case TypeNumber: return sprint(p, "%lld", a->intdata[i]); case TypeChar: return sprint(p, "%C", a->chardata[i]); case TypeArray: return printarraysub(p, a->arraydata[i], depth); default: return sprint(p, "???"); } } static int indent(char *buf, int depth) { char *p = buf; for(int i = 0; i < depth; i++) p += sprint(p, " "); return p-buf; } static int printarraysub(char *buf, Array *a, int depth) { char *p = buf; if(a->rank == 0){ p += printitem(p, a, 0, depth); goto end; }else if(a->rank == 1 && a->type == TypeNumber){ if(a->size == 0) p += sprint(p, "⍬"); for(uvlong i = 0; i < a->size; i++){ if(i != 0) p += sprint(p, " "); p += printitem(p, a, i, depth); } goto end; }else if(a->rank == 1 && a->type == TypeChar){ p += sprint(p, "'"); for(uvlong i = 0; i < a->size; i++) p += printitem(p, a, i, depth); /* TODO: quoting */ p += sprint(p, "'"); goto end; }else if(a->rank == 1 && a->type == TypeArray){ if(a->size == 0){ p += sprint(p, "( ⋄ )"); goto end; } p += sprint(p, "("); for(uvlong i = 0; i < a->size; i++){ if(i != 0){ p += sprint(p, "\n"); p += indent(p, depth+1); } p += printitem(p, a, i, depth+1); } p += sprint(p, ")"); goto end; } p += sprint(p, "Some array I can't print yet"); end: return p-buf; } char * printarray(Array *a) { char buf[2048]; /* TODO: fixed size :) */ printarraysub(buf, a, 0); return buf; } Array * simplifyarray(Array *a) { /* Given an array of type TypeArray, where all the elements are * simple scalars of the same type, return an array of that type */ Array *b = nil; int type; if(a->type != TypeArray || a->size == 0) goto end; type = a->arraydata[0]->type; b = allocarray(type, a->rank, a->size); for(uvlong dim = 0; dim < a->rank; dim++) b->shape[dim] = a->shape[dim]; for(uvlong i = 0; i < a->size; i++){ if(a->arraydata[i]->type != type || a->arraydata[i]->rank != 0){ b = a; goto end; /* Must be the same type and scalar */ } switch(type){ case TypeNumber: b->intdata[i] = a->arraydata[i]->intdata[0]; break; case TypeChar: b->chardata[i] = a->arraydata[i]->chardata[0]; break; } } end: return b; }