/* communicate an object to all other processors */ int COMOBJALL (MPI_Comm comm, OBJ_Pack pack, void *data, OBJ_Unpack unpack, void *object, COMOBJ **recv, int *nrecv) /* recv is contiguous => free (*recv) releases all memory */ { COMOBJ *send_data; int i, j, rank, ncpu, ret; if (object) { MPI_Comm_rank (comm, &rank); MPI_Comm_size (comm, &ncpu); ERRMEM (send_data = MEM_CALLOC ((ncpu - 1) * sizeof (COMOBJ))); for (i = j = 0; i < ncpu; i ++) { if (i != rank) { send_data [j].rank = i; send_data [j].o = object; j ++; } } ret = COMOBJSALL (comm, pack, data, unpack, send_data, ncpu - 1, recv, nrecv); free (send_data); } else ret = COMOBJSALL (comm, pack, data, unpack, NULL, 0, recv, nrecv); return ret; }
/* recursive create */ static KDT* create (KDT *u, int n, double **q) { KDT *kd; int k; ERRMEM (kd = MEM_CALLOC (sizeof (KDT))); kd->u = u; if (n == 0) { kd->d = -1; /* leaf */ return kd; } k = split (n, q, kd->p, &kd->d); if (k == -1) /* coincident points */ { kd->l = create (kd, 0, NULL); kd->r = create (kd, 0, NULL); } else { kd->l = create (kd, k, q); /* ends at q [k-1] */ kd->r = create (kd, n-k-1, q+k+1); /* starts at q [k+1] */ } return kd; }
/******************************************************************************* * * Render backend context functions. * ******************************************************************************/ int rb_create_context (struct mem_allocator* specific_allocator, struct rb_context** out_ctxt) { struct mem_allocator* allocator = NULL; struct rb_context* ctxt = NULL; int err = 0; if(!out_ctxt) goto error; allocator = specific_allocator ? specific_allocator : &mem_default_allocator; ctxt = MEM_CALLOC(allocator, 1, sizeof(struct rb_context)); if(!ctxt) goto error; ctxt->allocator = allocator; ref_init(&ctxt->ref); setup_config(&ctxt->config); exit: if(ctxt) *out_ctxt = ctxt; return err; error: if(ctxt) { RB(context_ref_put(ctxt)); ctxt = NULL; } err = -1; goto exit; }
/* unpack sphere from double and integer buffers (unpacking starts at dpos and ipos in * d and i and no more than a specific number of doubles and ints can be red) */ SPHERE* SPHERE_Unpack (void *solfec, int *dpos, double *d, int doubles, int *ipos, int *i, int ints) { SPHERE *sph; int j; ERRMEM (sph = MEM_CALLOC (sizeof (SPHERE))); sph->surface = unpack_int (ipos, i, ints); sph->volume = unpack_int (ipos, i, ints); unpack_doubles (dpos, d, doubles, sph->cur_center, 3); unpack_doubles (dpos, d, doubles, (double*)sph->cur_point, 9); sph->cur_radius = unpack_double (dpos, d, doubles); unpack_doubles (dpos, d, doubles, sph->ref_center, 3); unpack_doubles (dpos, d, doubles, (double*)sph->ref_point, 9); sph->ref_radius = unpack_double (dpos, d, doubles); j = unpack_int (ipos, i, ints); /* unpack material existence flag */ if (j) { SOLFEC *sol = solfec; char *label = unpack_string (ipos, i, ints); ASSERT_DEBUG_EXT (sph->mat = MATSET_Find (sol->mat, label), "Failed to find material when unpacking a sphere"); free (label); } return sph; }
/* communicate one set of integers and doubles to all other processors */ int COMONEALL (MPI_Comm comm, COMDATA send, COMDATA **recv, int *nrecv) /* recv is contiguous => free (*recv) releases all memory */ { COMDATA *send_data; int i, j, rank, ncpu, ret; MPI_Comm_rank (comm, &rank); MPI_Comm_size (comm, &ncpu); ERRMEM (send_data = MEM_CALLOC ((ncpu - 1) * sizeof (COMDATA))); for (i = 0; i < ncpu; i ++) { if (i != rank) { send_data [j] = send; send_data [j].rank = i; j ++; } } ret = COMALL (comm, send_data, ncpu - 1, recv, nrecv); free (send_data); return ret; }
/* unpack ellipsoid from double and integer buffers (unpacking starts at dpos and ipos in * d and i and no more than a specific number of doubles and ints can be red) */ ELLIP* ELLIP_Unpack (void *solfec, int *dpos, double *d, int doubles, int *ipos, int *i, int ints) { ELLIP *eli; int j; ERRMEM (eli = MEM_CALLOC (sizeof (ELLIP))); eli->surface = unpack_int (ipos, i, ints); eli->volume = unpack_int (ipos, i, ints); unpack_doubles (dpos, d, doubles, eli->cur_center, 3); unpack_doubles (dpos, d, doubles, (double*)eli->cur_point, 9); unpack_doubles (dpos, d, doubles, eli->ref_center, 3); unpack_doubles (dpos, d, doubles, (double*)eli->ref_point, 9); unpack_doubles (dpos, d, doubles, eli->ref_sca, 3); unpack_doubles (dpos, d, doubles, eli->ref_rot, 9); unpack_doubles (dpos, d, doubles, eli->cur_sca, 3); unpack_doubles (dpos, d, doubles, eli->cur_rot, 9); j = unpack_int (ipos, i, ints); /* unpack material existence flag */ if (j) { SOLFEC *sol = solfec; char *label = unpack_string (ipos, i, ints); ASSERT_DEBUG_EXT (eli->mat = MATSET_Find (sol->mat, label), "Failed to find material when unpacking a eliere"); free (label); } return eli; }
/******************************************************************************* * * Picking functions * ******************************************************************************/ enum edit_error edit_create_picking (struct app* app, struct edit_imgui* imgui, struct edit_model_instance_selection* instance_selection, struct mem_allocator* allocator, struct edit_picking** out_picking) { struct edit_picking* picking = NULL; enum edit_error edit_err = EDIT_NO_ERROR; enum sl_error sl_err = SL_NO_ERROR; if(UNLIKELY(!app || !instance_selection || !allocator || !out_picking)) { edit_err = EDIT_INVALID_ARGUMENT; goto error; } picking = MEM_CALLOC(allocator, 1, sizeof(struct edit_picking)); if(!picking) { edit_err = EDIT_MEMORY_ERROR; goto error; } ref_init(&picking->ref); APP(ref_get(app)); picking->app = app; EDIT(imgui_ref_get(imgui)); picking->imgui = imgui; EDIT(model_instance_selection_ref_get(instance_selection)); picking->instance_selection = instance_selection; picking->allocator = allocator; sl_err = sl_create_hash_table (sizeof(uint32_t), ALIGNOF(uint32_t), sizeof(uint32_t), ALIGNOF(uint32_t), hash_uint32, eq_uint32, allocator, &picking->picked_instances_htbl); if(sl_err != SL_NO_ERROR) { edit_err = sl_to_edit_error(sl_err); goto error; } exit: if(out_picking) *out_picking = picking; return edit_err; error: if(picking) { EDIT(picking_ref_put(picking)); picking = NULL; } goto exit; }
/******************************************************************************* * * Flat map functions. * ******************************************************************************/ EXPORT_SYM enum sl_error sl_create_flat_map (size_t key_size, size_t key_alignment, size_t data_size, size_t data_alignment, int (*cmp_key)(const void*, const void*), struct mem_allocator* specific_allocator, struct sl_flat_map** out_map) { struct mem_allocator* allocator = NULL; struct sl_flat_map* map = NULL; enum sl_error err = SL_NO_ERROR; if(!data_size || !key_size || !cmp_key || !out_map) { err = SL_INVALID_ARGUMENT; goto error; } if(!SL_IS_POWER_OF_2(data_alignment) || !SL_IS_POWER_OF_2(key_alignment)) { err = SL_ALIGNMENT_ERROR; goto error; } allocator = specific_allocator ? specific_allocator : &mem_default_allocator; map = MEM_CALLOC(allocator, 1, sizeof(struct sl_flat_map)); if(map == NULL) { err = SL_MEMORY_ERROR; goto error; } err = sl_create_flat_set (key_size, key_alignment, cmp_key, allocator, &map->key_set); if(err != SL_NO_ERROR) goto error; err = sl_create_vector(data_size, data_alignment, allocator, &map->data_list); if(err != SL_NO_ERROR) goto error; map->allocator = allocator; exit: if(out_map) *out_map = map; return err; error: if(map) { if(map->key_set) SL(free_flat_set(map->key_set)); if(map->data_list) SL(free_vector(map->data_list)); MEM_FREE(allocator, map); map = NULL; } goto exit; }
static SHAPE* psc_read_shape (FILE *f) { SHAPE *shp; ERRMEM (shp = MEM_CALLOC (sizeof (SHAPE))); shp->kind = SHAPE_MESH; shp->data = psc_read_mesh (f); return shp; }
/* levels: number of skip levels * compare: item key comparison (NULL implies pointer comparison) * return: skip list or NULL when out of memory; * create skip list */ LIST* LIST_Create (int levels, LIST_Compare compare) { LIST *list; if (!(list = malloc (sizeof (LIST)))) return NULL; MEM_Init (&list->mem, sizeof (ITEM) + levels * sizeof (ITEM*), CHUNK); list->maxlevel = levels - 1; list->level = 0; list->size = 0; if (!(list->header.forward = MEM_CALLOC (levels * sizeof (ITEM*)))) return NULL; if (!(list->update = malloc (levels * sizeof (ITEM*)))) return NULL; list->compare = compare; return list; }
static MX* psc_read_matrix (FILE *f) { MX *a; ERRMEM (a = MEM_CALLOC (sizeof (MX))); fread (&a->kind, sizeof (a->kind), 1, f); fread (&a->flags, sizeof (a->flags), 1, f); fread (&a->nzmax, sizeof (int), 1, f); fread (&a->m, sizeof (int), 1, f); fread (&a->n, sizeof (int), 1, f); fread (&a->nz, sizeof (int), 1, f); switch (a->kind) { case MXDENSE: { ERRMEM (a->x = malloc (a->nzmax * sizeof (double))); fread (a->x, sizeof (double), a->nzmax, f); } break; case MXBD: { ERRMEM (a->p = malloc ((a->n+1) * sizeof (int))); ERRMEM (a->i = malloc ((a->n+1) * sizeof (int))); ERRMEM (a->x = malloc (a->nzmax * sizeof (double))); fread (a->p, sizeof (int), a->n + 1, f); fread (a->i, sizeof (int), a->n + 1, f); fread (a->x, sizeof (double), a->nzmax, f); } break; case MXCSC: { ERRMEM (a->p = malloc ((a->n+1) * sizeof (int))); ERRMEM (a->i = malloc (a->nzmax * sizeof (int))); ERRMEM (a->x = malloc (a->nzmax * sizeof (double))); fread (a->p, sizeof (int), a->n + 1, f); fread (a->i, sizeof (int), a->nzmax, f); fread (a->x, sizeof (double), a->nzmax, f); } break; } return a; }
/******************************************************************************* * * Implementation of the vector container. * ******************************************************************************/ EXPORT_SYM enum sl_error sl_create_vector (size_t data_size, size_t data_alignment, struct mem_allocator* specific_allocator, struct sl_vector** out_vec) { struct mem_allocator* allocator = NULL; struct sl_vector* vec = NULL; enum sl_error err = SL_NO_ERROR; if(!out_vec || !data_size) { err = SL_INVALID_ARGUMENT; goto error; } if(!IS_POWER_OF_2(data_alignment)) { err = SL_ALIGNMENT_ERROR; goto error; } allocator = specific_allocator ? specific_allocator : &mem_default_allocator; vec = MEM_CALLOC(allocator, 1, sizeof(struct sl_vector)); if(vec == NULL) { err = SL_MEMORY_ERROR; goto error; } vec->allocator = allocator; vec->data_size = data_size; vec->data_alignment = data_alignment; exit: if(out_vec) *out_vec = vec; return err; error: if(vec) { ASSERT(allocator); MEM_FREE(allocator, vec); vec = NULL; } goto exit; }
hid_t dat1Reopen( hid_t file_id, unsigned int flags, hid_t fapl, int *status ){ /* Local Variables; */ HDSLoc **loc; HDSLoc **loclist; char **paths; char file[EMS__SZMSG+1]; char path[EMS__SZMSG+1]; hid_t *file_ids; hid_t id; int *isgroup; int iloc; int nlev; int nloc; ssize_t size; /* Return immediately if an error has already occurred. */ if( *status != SAI__OK ) return file_id; /* Get a list of any active locators associated with the file. Also get a list of file_ids for the same file that have associated locators. */ hds1GetLocators( file_id, &nloc, &loclist, &file_ids, status ); /* Check that none of the locators are mapped. */ if( *status == SAI__OK ) { loc = loclist; for( iloc = 0; iloc < nloc; iloc++,loc++ ) { if( (*loc)->regpntr ) { hdsTrace( (*loc), &nlev, path, file, status, sizeof(path), sizeof(file) ); *status = DAT__PRMAP; emsRepf( " ", "hdsOpen: Cannot re-open '%s' in read-write mode " "since '%s' is currently mapped.", status, file, path ); break; } } } /* Store the path to the HDF5 object associated with each active locator, and also a flag indicating if the HDF5 object is a group or dataset. Then close the HDF5 objects. */ paths = MEM_CALLOC( nloc, sizeof( *paths ) ); isgroup = MEM_CALLOC( nloc, sizeof( *isgroup ) ); if( paths && isgroup && *status == SAI__OK ) { loc = loclist; for( iloc = 0; iloc < nloc; iloc++,loc++ ) { if( (*loc)->group_id ) { isgroup[ iloc ] = 1; id = (*loc)->group_id; } else { isgroup[ iloc ] = 0; id = (*loc)->dataset_id; } if( id ) { size = H5Iget_name( id, NULL, 0 ); paths[ iloc ] = MEM_CALLOC( size + 1, 1 ); H5Iget_name( id, paths[ iloc ], size + 1 ); } else { hdsTrace( (*loc), &nlev, path, file, status, sizeof(path), sizeof(file) ); *status = DAT__FATAL; emsRepf( " ", "hdsOpen: Locator for '%s.%s' has no group or " "dataset so cannot be reopened.", status, file, path ); break; } if( H5Oclose( id ) < 0 ) { hdsTrace( (*loc), &nlev, path, file, status, sizeof(path), sizeof(file) ); *status = DAT__FATAL; dat1H5EtoEMS( status ); emsRepf( " ", "hdsOpen: Failed to close HDF5 object for '%s.%s'.", status, file, path ); break; } } } /* Get the path for the file. */ H5Fget_name( file_id, path, sizeof(path) ); /* Close all HDF5 file_ids associated with file. */ if( *status == SAI__OK ) { int this_closed = 0; int i = -1; while( file_ids[ ++i ] ) { if( file_ids[ i ] == file_id ) this_closed = 1; if( H5Fclose( file_ids[ i ] ) < 0 ) { *status = DAT__FATAL; dat1H5EtoEMS( status ); emsRepf( " ", "hdsOpen: Failed to close file '%s' prior to " "re-opening it.", status, path ); break; } } /* Close the supplied file_id if it has not already been closed. */ if( !this_closed ) { if( H5Fclose( file_id ) < 0 ) { *status = DAT__FATAL; dat1H5EtoEMS( status ); emsRepf( " ", "hdsOpen: Failed to close file '%s' prior to " "re-opening it.", status, path ); } } } /* Re-open it. */ if( *status == SAI__OK ) { file_id = H5Fopen( path, flags, fapl ); if( file_id < 0 ) { *status = DAT__FATAL; dat1H5EtoEMS( status ); emsRepf( " ", "hdsOpen: Failed to reopen file '%s'.", status, path ); } } /* Update the file, group and dataset id in each locator. */ if( *status == SAI__OK ) { loc = loclist; for( iloc = 0; iloc < nloc; iloc++,loc++ ) { hds1SetFileId( (*loc), file_id, status ); if( isgroup[ iloc ] ) { (*loc)->group_id = H5Gopen2( file_id, paths[ iloc ], H5P_DEFAULT ); } else { (*loc)->dataset_id = H5Dopen2( file_id, paths[ iloc ], H5P_DEFAULT ); } } } /* Free resources. */ if( paths ) { for( iloc = 0; iloc < nloc; iloc++ ) { MEM_FREE( paths[ iloc ] ); } MEM_FREE( paths ); } if( isgroup ) MEM_FREE( isgroup ); if( loclist ) MEM_FREE( loclist ); if( file_ids ) MEM_FREE( file_ids ); /* Return the new file id. */ return file_id; }
static MESH* psc_read_mesh (FILE *f) { ELEMENT *ele, **tab, *tail; MESH *msh; int i, j; ERRMEM (msh = MEM_CALLOC (sizeof (MESH))); MEM_Init (&msh->elemem, sizeof (ELEMENT), 128); MEM_Init (&msh->facmem, sizeof (FACE), 128); MEM_Init (&msh->mapmem, sizeof (MAP), 128); fread (&msh->nodes_count, sizeof (int), 1, f); ERRMEM (msh->ref_nodes = malloc (2 * msh->nodes_count * sizeof (double [3]))); msh->cur_nodes = msh->ref_nodes + msh->nodes_count; fread (msh->ref_nodes, sizeof (double [3]), msh->nodes_count, f); fread (msh->cur_nodes, sizeof (double [3]), msh->nodes_count, f); fread (&msh->surfeles_count, sizeof (int), 1, f); fread (&msh->bulkeles_count, sizeof (int), 1, f); ERRMEM (tab = malloc ((msh->surfeles_count + msh->bulkeles_count) * sizeof (ELEMENT*))); for (i = 0, tail = NULL; i < msh->surfeles_count; i ++) { ele = psc_read_element (&msh->elemem, &msh->facmem, f); ele->flag = i; if (tail) ele->prev = tail, tail->next = ele; else msh->surfeles = ele; tail = ele; tab [i] = ele; } for (tail = NULL; i < msh->surfeles_count + msh->bulkeles_count; i ++) { ele = psc_read_element (&msh->elemem, &msh->facmem, f); ele->flag = i; if (tail) ele->prev = tail, tail->next = ele; else msh->bulkeles = ele; tail = ele; tab [i] = ele; } for (i = 0; i < msh->surfeles_count + msh->bulkeles_count; i ++) { ele = tab [i]; for (j = 0; j < ele->neighs; j ++) { int idx = (long) (void*) ele->adj[j]; ASSERT_TEXT (idx >= 0 && idx < msh->surfeles_count + msh->bulkeles_count, "INCONSITENT ELEMENT INDEXING"); ele->adj[j] = tab [idx]; } } free (tab); return msh; }
int main(int argc, char** argv) { /* Check command arguments */ if(argc != 3) { printf("usage: %s RB_DRIVER FONT\n", argv[0]); return -1; } const char* driver_name = argv[1]; const char* font_name = argv[2]; FILE* file = fopen(driver_name, "r"); if(!file) { fprintf(stderr, "Invalid driver %s\n", driver_name); return -1; } fclose(file); file = fopen(font_name, "r"); if(!file) { fprintf(stderr, "Invalid font name %s\n", font_name); return -1; } fclose(file); /* Spawn a drawable windows */ struct wm_device* device = NULL; struct wm_window* window = NULL; const struct wm_window_desc win_desc = { .width = 640, .height = 480, .fullscreen = false }; WM(create_device(NULL, &device)); WM(create_window(device, &win_desc, &window)); /* Create a render backend */ struct rbi rbi; struct rb_context* rb_ctxt = NULL; CHECK(rbi_init(driver_name, &rbi), 0); RBI(&rbi, create_context(NULL, &rb_ctxt)); /* Load font resource */ struct font_system* font_sys = NULL; struct font_rsrc* font_rsrc = NULL; bool is_font_scalable = false; int line_space = 0; FONT(system_create(NULL, &font_sys)); FONT(rsrc_create(font_sys, font_name, &font_rsrc)); FONT(rsrc_get_line_space(font_rsrc, &line_space)); FONT(rsrc_is_scalable(font_rsrc, &is_font_scalable)); if(is_font_scalable) { FONT(rsrc_set_size(font_rsrc, 24, 24)); } /* Build x charset description */ int glyph_min_width = INT_MAX; const wchar_t* charset = L"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" L" &~\"#'{([-|`_\\^@)]=}+$%*,?;.:/!<>"; const size_t charset_len = wcslen(charset); size_t i = 0; struct lp_font_glyph_desc lp_font_glyph_desc_list[512]; unsigned char* glyph_bitmap_list[512]; ASSERT(charset_len <= 512); for(i = 0; i < charset_len; ++i) { struct font_glyph_desc font_glyph_desc; struct font_glyph* font_glyph = NULL; int width = 0; int height = 0; int Bpp = 0; FONT(rsrc_get_glyph(font_rsrc, charset[i], &font_glyph)); FONT(glyph_get_desc(font_glyph, &font_glyph_desc)); glyph_min_width = MIN(font_glyph_desc.width, glyph_min_width); lp_font_glyph_desc_list[i].width = font_glyph_desc.width; lp_font_glyph_desc_list[i].character = font_glyph_desc.character; lp_font_glyph_desc_list[i].bitmap_left = font_glyph_desc.bbox.x_min; lp_font_glyph_desc_list[i].bitmap_top = font_glyph_desc.bbox.y_min; FONT(glyph_get_bitmap(font_glyph, true, &width, &height, &Bpp, NULL)); if(width && height ) { glyph_bitmap_list[i] = MEM_CALLOC (&mem_default_allocator, (size_t)(width*height), (size_t)Bpp); NCHECK(glyph_bitmap_list[i], NULL); FONT(glyph_get_bitmap (font_glyph, true, &width, &height, &Bpp, glyph_bitmap_list[i])); } lp_font_glyph_desc_list[i].bitmap.width = width; lp_font_glyph_desc_list[i].bitmap.height = height; lp_font_glyph_desc_list[i].bitmap.bytes_per_pixel = Bpp; lp_font_glyph_desc_list[i].bitmap.buffer = glyph_bitmap_list[i]; FONT(glyph_ref_put(font_glyph)); } /* Create the lp system and font */ struct lp* lp = NULL; struct lp_font* lp_font = NULL; LP(create(&rbi, rb_ctxt, NULL, &lp)); LP(font_create(lp, &lp_font)); LP(font_set_data (lp_font, line_space, (int)charset_len, lp_font_glyph_desc_list)); /* Create the printer */ struct lp_printer* lp_printer = NULL; LP(printer_create(lp, &lp_printer)); LP(printer_set_font(lp_printer, lp_font)); LP(printer_set_viewport(lp_printer, 0, 0, win_desc.width, win_desc.height)); enum wm_state esc = WM_STATE_UNKNOWN; do { int cur[2] = { 0, 0 }; RBI(&rbi, clear (rb_ctxt, RB_CLEAR_COLOR_BIT, (float[]){0.05f, 0.05f, 0.05f}, 0.f, 0)); LP(printer_print_wstring (lp_printer, 50, 70, L">$ ", (float[]){0.f, 1.f, 0.f}, cur+0, cur+1)); LP(printer_print_wstring (lp_printer, cur[0], cur[1], L"Hello", (float[]){1.f, 1.f, 1.f}, cur+0, cur+1));
/* read fracture state */ FS* fracture_state_read (BODY *bod) { FS *out = NULL, *item, *instance; char path [1024]; unsigned int id; int i, n, dofs; double *disp; #if HDF5 PBF *f, *g; snprintf (path, 1024, "%s/fracture", bod->dom->solfec->outpath); g = PBF_Read (path); do { double time; PBF_Time (g, &time); /* unused, but could be useful at some point */ for (f = g; f; f = f->next) { int numbod; PBF_Int2 (f, "numbod", &numbod, 1); while (numbod > 0) { PBF_Uint (f, &id, 1); PBF_Int (f, &dofs, 1); ERRMEM (disp = malloc (dofs * sizeof (double))); PBF_Double (f, disp, dofs); PBF_Int (f, &n, 1); for (i = 0, instance = NULL; i < n; i ++) { ERRMEM (item = MEM_CALLOC (sizeof (FS))); PBF_Double (f, &item->radius, 1); PBF_Double (f, item->point, 3); PBF_Double (f, item->force, 3); if (id == bod->id) { item->inext = instance; instance = item; if (i == (n-1)) { item->disp = disp; /* put displacements into first element of instance list */ item->next = out; out = item; } } else free (item); } if (!out || out->disp != disp) free (disp); /* not used */ numbod --; } } } while (PBF_Forward (g, 1)); PBF_Close (g); #else FILE *f; XDR x; snprintf (path, 1024, "%s/fracture.dat", bod->dom->solfec->outpath); f = fopen (path, "r"); /* TODO: read MPI mode data in case f == NULL but fractureRANK.dat exit */ if (f) { xdrstdio_create (&x, f, XDR_DECODE); while (! feof (f)) { if (xdr_u_int (&x, &id) == 0) break; ASSERT (xdr_int (&x, &dofs), ERR_FILE_READ); ERRMEM (disp = malloc (dofs * sizeof (double))); ASSERT (xdr_vector (&x, (char*)disp, dofs, sizeof (double), (xdrproc_t)xdr_double), ERR_FILE_READ); ASSERT (xdr_int (&x, &n), ERR_FILE_READ); for (i = 0, instance = NULL; i < n; i ++) { ERRMEM (item = MEM_CALLOC (sizeof (FS))); ASSERT (xdr_double (&x, &item->radius), ERR_FILE_READ); ASSERT (xdr_vector (&x, (char*)item->point, 3, sizeof (double), (xdrproc_t)xdr_double), ERR_FILE_READ); ASSERT (xdr_vector (&x, (char*)item->force, 3, sizeof (double), (xdrproc_t)xdr_double), ERR_FILE_READ); if (id == bod->id) { item->inext = instance; instance = item; if (i == (n-1)) { item->disp = disp; /* put displacements into first element of instance list */ item->next = out; out = item; } } else free (item); } if (!out || out->disp != disp) free (disp); /* not used */ } xdr_destroy (&x); fclose (f); } #endif return out; }
Handle *dat1HandleLock( Handle *handle, int oper, int recurs, int rdonly, int *result, int *status ){ /* Local Variables; */ Handle *child; int ichild; int top_level; pthread_t *locker; pthread_t *rlocker; int i; int j; Handle *error_handle = NULL; int child_result; /* initialise */ *result = 0; /* Check inherited status. */ if( *status != SAI__OK ) return error_handle; /* Validate the supplied Handle */ if( !dat1ValidateHandle( "dat1HandleLock", handle, status ) ) return error_handle; /* To avoid deadlocks, we only lock the Handle mutex for top level entries to this function. If "oper" is negative, negate it and set a flag indicating we do not need to lock the mutex. */ if( oper < 0 ) { oper = -oper; top_level = 0; } else { top_level = 1; } /* For top-level entries to this function, we need to ensure no other thread is modifying the details in the handle, so attempt to lock the handle's mutex. */ if( top_level ) pthread_mutex_lock( &(handle->mutex) ); /* Return information about the current lock on the supplied Handle. ------------------------------------------------------------------ */ if( oper == 1 ) { /* Default: unlocked */ if( handle->nwrite_lock ) { if( pthread_equal( handle->write_locker, pthread_self() )) { /* Locked for writing by the current thread. */ *result = 1; } else { /* Locked for writing by another thread. */ *result = 2; } } else if( handle->nread_lock ){ /* Locked for reading by one or more other threads (the current thread does not have a read lock on the Handle). */ *result = 4; /* Now check to see if the current thread has a read lock, changing the above result value if it does. */ locker = handle->read_lockers; for( i = 0; i < handle->nread_lock;i++,locker++ ) { if( pthread_equal( *locker, pthread_self() )) { /* Locked for reading by the current thread (other threads may also have a read lock on the Handle). */ *result = 3; break; } } } /* If required, check any child handles. If we already have a status of 2, (the supplied handle is locked read-write by another thread), we do not need to check the children. */ if( recurs && *result != 2 ){ for( ichild = 0; ichild < handle->nchild; ichild++ ) { child = handle->children[ichild]; if( child ) { /* Get the lock status of the child. */ (void) dat1HandleLock( child, -1, 1, rdonly, &child_result, status ); /* If it's 2, we can set the final result and exit immediately. */ if( child_result == 2 ) { *result = 2; break; /* Otherwise, ensure the child gives the same result as all the others, breaking out and returning the catch-all value if not. */ } else if( child_result != *result ) { *result = 5; break; } } } } /* Lock the handle for use by the current thread. ------------------------------------------------------------------ */ } else if( oper == 2 ) { /* A read-only lock requested.... */ if( rdonly ) { /* If the current thread has a read-write lock on the Handle, demote it to a read-only lock and return 1 (success). In this case, we know there will be no other read-locks. Otherwise if any other thread has read-write lock, return zero (failure). */ if( handle->nwrite_lock ) { if( pthread_equal( handle->write_locker, pthread_self() )) { /* If we do not have an array in which to store read lock thread IDs, allocate one now with room for NTHREAD locks. It will be extended as needed. */ if( !handle->read_lockers ) { handle->read_lockers = MEM_CALLOC(NTHREAD,sizeof(pthread_t)); if( !handle->read_lockers ) { *status = DAT__NOMEM; emsRep( "", "Could not allocate memory for HDS " "Handle read locks list.", status ); } } /* If we now have an array, store the current thread in the first element. */ if( handle->read_lockers ) { handle->read_lockers[ 0 ] = pthread_self(); handle->nread_lock = 1; handle->nwrite_lock = 0; *result = 1; } } /* If there is no read-write lock on the Handle, add the current thread to the list of threads that currently have a read-only lock, but only if it is not already there. */ } else { /* Set "result" to 1 if the current thread already has a read-only lock. */ locker = handle->read_lockers; for( i = 0; i < handle->nread_lock;i++,locker++ ) { if( pthread_equal( *locker, pthread_self() )) { *result = 1; break; } } /* If not, extend the read lock thread ID array if necessary, and append the current thread ID to the end. */ if( *result == 0 ) { handle->nread_lock++; if( handle->maxreaders < handle->nread_lock ) { handle->maxreaders += NTHREAD; handle->read_lockers = MEM_REALLOC( handle->read_lockers, handle->maxreaders*sizeof(pthread_t)); if( !handle->read_lockers ) { *status = DAT__NOMEM; emsRep( "", "Could not reallocate memory for HDS " "Handle read locks list.", status ); } } if( handle->read_lockers ) { handle->read_lockers[ handle->nread_lock - 1 ] = pthread_self(); /* Indicate the read-only lock was applied successfully. */ *result = 1; } } } /* A read-write lock requested. */ } else { /* If there are currently no locks of any kind, apply the lock. */ if( handle->nread_lock == 0 ) { if( handle->nwrite_lock == 0 ) { handle->write_locker = pthread_self(); handle->nwrite_lock = 1; *result = 1; /* If the current thread already has a read-write lock, indicate success. */ } else if( pthread_equal( handle->write_locker, pthread_self() )) { *result = 1; } /* If there is currently only one read-only lock, and it is owned by the current thread, then promote it to a read-write lock. */ } else if( handle->nread_lock == 1 && pthread_equal( handle->read_lockers[0], pthread_self() )) { handle->nread_lock = 0; handle->write_locker = pthread_self(); handle->nwrite_lock = 1; *result = 1; } } /* If required, and if the above lock operation was successful, lock any child handles that can be locked. */ if( *result ){ if( recurs ){ for( ichild = 0; ichild < handle->nchild; ichild++ ) { child = handle->children[ichild]; if( child ) { error_handle = dat1HandleLock( child, -2, 1, rdonly, result, status ); if( error_handle ) break; } } } /* If the lock operation failed, return a pointer to the Handle. */ } else { error_handle = handle; } /* Unlock the handle. ----------------- */ } else if( oper == 3 ) { /* Assume failure. */ *result = 0; /* If the current thread has a read-write lock, remove it. */ if( handle->nwrite_lock ) { if( pthread_equal( handle->write_locker, pthread_self() )) { handle->nwrite_lock = 0; *result = 1; } else { *result = -1; } /* Otherwise, if the current thread has a read-only lock, remove it. */ } else { /* Loop through all the threads that have read-only locks. */ locker = handle->read_lockers; for( i = 0; i < handle->nread_lock; i++,locker++ ) { /* If the current thread is found, shuffle any remaining threads down one slot to fill the gap left by removing the current thread from the list. */ if( pthread_equal( *locker, pthread_self() )) { rlocker = locker + 1; for( j = i + 1; j < handle->nread_lock; j++,locker++ ) { *locker = *(rlocker++); } /* Reduce the number of read-only locks. */ handle->nread_lock--; *result = 1; break; } } } /* If required, and if the above unlock operation was successful, unlock any child handles that can be unlocked. */ if( *result == 1 ){ if( recurs ){ for( ichild = 0; ichild < handle->nchild; ichild++ ) { child = handle->children[ichild]; if( child ) { error_handle = dat1HandleLock( child, -3, 1, 0, result, status ); if( error_handle ) break; } } } /* If the unlock operation failed, return a pointer to the Handle. */ } else { error_handle = handle; } /* Report an error for any other "oper" value. */ } else if( *status == SAI__OK ) { *status = DAT__FATAL; emsRepf( " ", "dat1HandleLock: Unknown 'oper' value (%d) supplied - " "(internal HDS programming error).", status, oper ); } /* If this is a top-level entry, unlock the Handle's mutex so that other threads can access the values in the Handle. */ if( top_level ) pthread_mutex_unlock( &(handle->mutex) ); /* Return the error handle. */ return error_handle; }
static void regular_test(struct mem_allocator* allocator) { char dump[BUFSIZ]; void* p = NULL; void* q[3] = {NULL, NULL, NULL}; size_t i = 0; p = MEM_ALIGNED_ALLOC(allocator, 1024, ALIGNOF(char)); NCHECK(p, NULL); CHECK(IS_ALIGNED((uintptr_t)p, ALIGNOF(char)), 1); MEM_FREE(allocator, p); q[0] = MEM_ALIGNED_ALLOC(allocator, 10, 8); q[1] = MEM_CALLOC(allocator, 1, 58); q[2] = MEM_ALLOC(allocator, 78); NCHECK(q[0], NULL); NCHECK(q[1], NULL); NCHECK(q[2], NULL); CHECK(IS_ALIGNED((uintptr_t)q[0], 8), 1); p = MEM_CALLOC(allocator, 2, 2); NCHECK(p, NULL); for(i = 0; i < 4; ++i) CHECK(((char*)p)[i], 0); for(i = 0; i < 4; ++i) ((char*)p)[i] = (char)i; MEM_DUMP(allocator, dump, BUFSIZ); printf("dump:\n%s\n", dump); MEM_DUMP(allocator, dump, 16); printf("truncated dump:\n%s\n", dump); MEM_DUMP(allocator, NULL, 0); /* may not crashed. */ MEM_FREE(allocator, q[1]); p = MEM_REALLOC(allocator, p, 8); for(i = 0; i < 4; ++i) CHECK(((char*)p)[i], (char)i); for(i = 4; i < 8; ++i) ((char*)p)[i] = (char)i; MEM_FREE(allocator, q[2]); p = MEM_REALLOC(allocator, p, 5); for(i = 0; i < 5; ++i) CHECK(((char*)p)[i], (char)i); MEM_FREE(allocator, p); p = NULL; p = MEM_REALLOC(allocator, NULL, 16); NCHECK(p, NULL); p = MEM_REALLOC(allocator, p, 0); MEM_FREE(allocator, q[0]); CHECK(MEM_ALIGNED_ALLOC(allocator, 1024, 0), NULL); CHECK(MEM_ALIGNED_ALLOC(allocator, 1024, 3), NULL); CHECK(MEM_ALLOCATED_SIZE(allocator), 0); }
int main(int argc, char** argv) { /* Window manager data structures. */ struct wm_device* dev = NULL; struct wm_window* win = NULL; const struct wm_window_desc win_desc = { 800, 600, 0 }; /* Renderer data structure. */ struct rdr_glyph_desc glyph_desc_list[NB_CHARS]; struct rdr_font* font = NULL; struct rdr_frame* frame = NULL; struct rdr_system* sys = NULL; struct rdr_term* term = NULL; /* Resources data structure. */ struct rsrc_context* ctxt = NULL; struct rsrc_font* rfont = NULL; /* Miscellaneous data. */ const char* driver_name = NULL; const char* font_name = NULL; size_t line_space = 0; size_t i = 0; bool b = false; if(argc != 3) { printf("usage: %s RB_DRIVER FONT\n", argv[0]); return -1; } driver_name = argv[1]; font_name = argv[2]; /* Setup the render font. */ RSRC(create_context(NULL, &ctxt)); RSRC(create_font(ctxt, font_name, &rfont)); if(RSRC(is_font_scalable(rfont, &b)), b) RSRC(font_size(rfont, 18, 18)); for(i = 0; i < NB_CHARS; ++i) { struct rsrc_glyph* glyph = NULL; struct rsrc_glyph_desc glyph_desc; size_t width = 0; size_t height = 0; size_t Bpp = 0; size_t size = 0; RSRC(font_glyph(rfont, (wchar_t)(i + FIRST_CHAR), &glyph)); /* Get glyph desc. */ RSRC(glyph_desc(glyph, &glyph_desc)); glyph_desc_list[i].width = glyph_desc.width; glyph_desc_list[i].character = glyph_desc.character; glyph_desc_list[i].bitmap_left = glyph_desc.bbox.x_min; glyph_desc_list[i].bitmap_top = glyph_desc.bbox.y_min; /* Get glyph bitmap. */ RSRC(glyph_bitmap(glyph, true, &width, &height, &Bpp, NULL)); glyph_desc_list[i].bitmap.width = width; glyph_desc_list[i].bitmap.height = height; glyph_desc_list[i].bitmap.bytes_per_pixel = Bpp; glyph_desc_list[i].bitmap.buffer = NULL; size = width * height * Bpp; if(0 != size) { unsigned char* buffer = MEM_CALLOC(&mem_default_allocator, 1, size); RSRC(glyph_bitmap(glyph, true, NULL, NULL, NULL, buffer)); glyph_desc_list[i].bitmap.buffer = buffer; } RSRC(glyph_ref_put(glyph)); } RSRC(font_line_space(rfont, &line_space)); RSRC(font_ref_put(rfont)); RSRC(context_ref_put(ctxt)); WM(create_device(NULL, &dev)); WM(create_window(dev, &win_desc, &win)); RDR(create_system(driver_name, NULL, &sys)); RDR(create_frame (sys, (struct rdr_frame_desc[]){{win_desc.width,win_desc.height}}, &frame));
/* communicate integers and doubles using all to all communication */ int COMALL (MPI_Comm comm, COMDATA *send, int nsend, COMDATA **recv, int *nrecv) /* recv is contiguous => free (*recv) releases all memory */ { COMDATA *cd; int rank, ncpu, (*send_sizes) [3], *send_counts, *send_disps, *send_position, send_size, (*recv_sizes) [3], *recv_counts, *recv_disps, *recv_position, recv_size, i, j, k; char *send_data, *recv_data; void *p; MPI_Comm_rank (comm, &rank); MPI_Comm_size (comm, &ncpu); ERRMEM (send_sizes = MEM_CALLOC (ncpu * sizeof (int [3]))); ERRMEM (send_counts = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (send_disps = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (send_position = MEM_CALLOC (ncpu * sizeof (int))); /* compute send sizes */ for (i = 0, cd = send; i < nsend; i ++, cd ++) { send_sizes [cd->rank][0] += cd->ints; send_sizes [cd->rank][1] += cd->doubles; MPI_Pack_size (cd->ints, MPI_INT, comm, &j); MPI_Pack_size (cd->doubles, MPI_DOUBLE, comm, &k); send_sizes [cd->rank][2] += (j + k); } /* compute send displacements */ for (send_size = i = 0; i < ncpu; i ++) { send_counts [i] = send_sizes [i][2]; send_size += send_counts [i]; if (i < (ncpu - 1)) send_disps [i+1] = send_size; } send_disps [0] = 0; /* allocate send buffer */ ERRMEM (send_data = malloc (send_size)); /* pack ints */ for (i = 0, cd = send; i < nsend; i ++, cd ++) { if (cd->ints) { MPI_Pack (cd->i, cd->ints, MPI_INT, &send_data [send_disps [cd->rank]], send_counts [cd->rank], &send_position [cd->rank], comm); } } /* pack doubles */ for (i = 0, cd = send; i < nsend; i ++, cd ++) { if (cd->doubles) { MPI_Pack (cd->d, cd->doubles, MPI_DOUBLE, &send_data [send_disps [cd->rank]], send_counts [cd->rank], &send_position [cd->rank], comm); } } #if DEBUG for (i = 0; i < ncpu; i ++) { ASSERT_DEBUG (send_position [i] <= send_counts [i], "Incorrect packing"); } #endif ERRMEM (recv_sizes = MEM_CALLOC (ncpu * sizeof (int [3]))); ERRMEM (recv_counts = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (recv_disps = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (recv_position = MEM_CALLOC (ncpu * sizeof (int))); /* distribute send sizes into receive sizes */ MPI_Alltoall (send_sizes, 3, MPI_INT, recv_sizes, 3, MPI_INT, comm); /* compute receive displacements */ for (recv_size = i = 0; i < ncpu; i ++) { recv_counts [i] = recv_sizes [i][2]; recv_size += recv_counts [i]; if (i < (ncpu - 1)) recv_disps [i+1] = recv_size; } recv_disps [0] = 0; /* allocate receive buffer */ ERRMEM (recv_data = malloc (recv_size)); /* all to all send and receive */ MPI_Alltoallv (send_data, send_counts, send_disps, MPI_PACKED, recv_data, recv_counts, recv_disps, MPI_PACKED, comm); if (recv_size) { /* contiguous receive size */ j = ncpu * sizeof (COMDATA); for (i = 0; i < ncpu; i ++) { j += recv_sizes [i][0] * sizeof (int) + recv_sizes [i][1] * sizeof (double); } /* prepare output receive data */ ERRMEM ((*recv) = malloc (j)); p = (*recv) + ncpu; for (i = 0, cd = *recv; i < ncpu; i ++, cd ++) { cd->rank = i; cd->ints = recv_sizes [i][0]; cd->doubles = recv_sizes [i][1]; cd->i = p; p = (cd->i + cd->ints); cd->d = p; p = (cd->d + cd->doubles); } /* unpack data */ for (i = 0; i < ncpu; i ++) { MPI_Unpack (&recv_data [recv_disps [i]], recv_counts [i], &recv_position [i], (*recv) [i].i, (*recv) [i].ints, MPI_INT, comm); MPI_Unpack (&recv_data [recv_disps [i]], recv_counts [i], &recv_position [i], (*recv) [i].d, (*recv) [i].doubles, MPI_DOUBLE, comm); } /* compress receive storage */ for (*nrecv = i = 0; i < ncpu; i ++) { if (recv_counts [i]) { (*recv) [*nrecv] = (*recv) [i]; (*nrecv) ++; } } } else { *recv = NULL; *nrecv = 0; } /* cleanup */ free (send_sizes); free (send_counts); free (send_disps); free (send_position); free (recv_sizes); free (recv_counts); free (recv_disps); free (recv_position); free (send_data); free (recv_data); return send_size; }
/* create rank coloring using adjacency graph between processors derived from the W graph */ static int* processor_coloring (GAUSS_SEIDEL *gs, LOCDYN *ldy) { int i, n, m, ncpu, rank, *color, *size, *disp, *adj; SET *adjcpu, *item; MEM setmem; DIAB *dia; OFFB *blk; CON *con; adjcpu = NULL; rank = ldy->dom->rank; ncpu = ldy->dom->ncpu; MEM_Init (&setmem, sizeof (SET), 128); ERRMEM (color = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (disp = malloc (sizeof (int [ncpu + 1]))); ERRMEM (size = malloc (sizeof (int [ncpu]))); /* collaps W adjacency into processor adjacency */ for (dia = ldy->dia; dia; dia = dia->n) { for (blk = dia->adjext; blk; blk = blk->n) { con = (CON*) blk->dia; SET_Insert (&setmem, &adjcpu, (void*) (long) con->rank, NULL); } } n = SET_Size (adjcpu); MPI_Allgather (&n, 1, MPI_INT, size, 1, MPI_INT, MPI_COMM_WORLD); for (i = disp [0] = 0; i < ncpu - 1; i ++) disp [i+1] = disp [i] + size [i]; for (i = 0, item = SET_First (adjcpu); item; i ++, item = SET_Next (item)) color [i] = (int) (long) item->data; m = disp [ncpu] = (disp [ncpu-1] + size [ncpu-1]); ERRMEM (adj = malloc (sizeof (int [m]))); MPI_Allgatherv (color, n, MPI_INT, adj, size, disp, MPI_INT, MPI_COMM_WORLD); /* gather graph adjacency */ for (i = 0; i < ncpu; i ++) color [i] = 0; /* zero colors */ for (i = 0; i < ncpu; i ++) /* simple BFS coloring */ { int *j, *k; do { color [i] ++; /* start from first color */ for (j = &adj[disp[i]], k = &adj[disp[i+1]]; j < k; j ++) /* for each adjacent vertex */ { if (color [*j] == color [i]) break; /* see whether the trial color exists in the adjacency */ } } while (j < k); /* if so try next color */ } for (m = i = 0; i < ncpu; i ++) m = MAX (m, color [i]); /* compute number of colors */ gs->colors = m; /* record number of colors */ if (rank == 0 && ldy->dom->verbose && gs->verbose) { #if DEBUG for (i = 0; i < ncpu; i ++) { int *j, *k; printf ("GAUSS_SEIDEL: RANK %d [%d] ADJCPU:", i, color [i]); for (j = &adj[disp[i]], k = &adj[disp[i+1]]; j < k; j ++) printf (" %d [%d]", *j, color [*j]); printf ("\n"); } #endif printf ("GAUSS_SEIDEL: PROCESSOR COLORS = %d\n", m); } MEM_Release (&setmem); free (size); free (disp); free (adj); return color; }
/* create mesh from a vector of nodes, element list in format => * {nuber of nodes, node0, node1, ..., material}, {REPEAT}, ..., 0 (end of list); and surface colors in format => * global surface, {number of nodes, node0, node1, ..., surface}, {REPEAT}, ..., 0 (end of list); */ MESH_DATA* MESH_Create (REAL (*nodes) [3], int *elements, int *surfaces) { int maximal_node, minimal_node, elements_count, faces_count, temp, *eleptr, n; REAL (*node) [3]; MEM *elemem, facmem, mapmem; ELEMENT *ele, *enx, *elist; FACE *fac, *cac, *gac, *flist; MAP *faces, *smap; MESH_DATA *msh; maximal_node = 0; minimal_node = INT_MAX; elements_count = 0; faces_count = 0; /* create mesh storage */ ERRMEM (msh = static_cast<MESH_DATA*>(MEM_CALLOC (sizeof (MESH_DATA)))); elemem = &msh->elemem; /* calculate elements */ for (eleptr = elements; eleptr [0]; eleptr += (eleptr [0]+2)) elements_count ++; MEM_Init (elemem, sizeof (ELEMENT), elements_count); MEM_Init (&facmem, sizeof (FACE), MEMCHUNK); MEM_Init (&mapmem, sizeof (MAP), MEMCHUNK); MEM_Init (&msh->mapmem, sizeof (MAP), MIN (elements_count, MEMCHUNK)); elist = NULL; flist = NULL; faces = NULL; /* create elements list & face adjacency map */ for (eleptr = elements; eleptr [0]; eleptr += (eleptr [0]+2)) { ASSERT ( eleptr [0] == 4 || /* tetrahedron */ eleptr [0] == 5 || /* pyramid */ eleptr [0] == 6 || /* wedge */ eleptr [0] == 8, /* hexahedron */ "ERROR: unsupported element type"); ele = create_element (elemem, eleptr); flist = create_faces (&facmem, &mapmem, &faces, ele, flist); ele->next = elist; elist = ele; /* node number extrema */ temp = maximal (eleptr); if (temp > maximal_node) maximal_node = temp; temp = minimal (eleptr); if (temp < minimal_node) minimal_node = temp; } /* calculate faces */ for (fac = flist; fac; fac = fac->next) if (fac->ele) faces_count ++; /* alocate additional storage */ MEM_Init (&msh->facmem, sizeof (FACE), faces_count); msh->nodes_count = (maximal_node - minimal_node + 1); ERRMEM (msh->nodes = static_cast<REAL(*)[3]>(malloc (sizeof (REAL [3]) * (msh->nodes_count)))); msh->surfeles_count = msh->bulkeles_count = 0; msh->surfeles = msh->bulkeles = NULL; /* set up elements */ for (ele = elist; ele; ele = enx) { enx = ele->next; if (minimal_node > 0) /* impose 0-based indexing */ { for (temp = 0; temp < ele->type; temp ++) ele->nodes [temp] -= minimal_node; } ele->prev = NULL; if (ele->neighs < neighs (ele->type)) /* surface element */ { msh->surfeles_count ++; ele->next = msh->surfeles; if (msh->surfeles) msh->surfeles->prev = ele; msh->surfeles = ele; } else /* bulk element */ { msh->bulkeles_count ++; ele->next = msh->bulkeles; if (msh->bulkeles) msh->bulkeles->prev = ele; msh->bulkeles = ele; } } /* create surfaces map => skip first element of 'surfaces' == the global surface kind */ for (eleptr = (surfaces + 1), smap = NULL, temp = 0; eleptr [0]; eleptr += (eleptr [0]+2), temp ++) { fac = static_cast<FACE*>(MEM_Alloc (&facmem)); ASSERT ( eleptr [0] == 3 || /* triangle */ eleptr [0] == 4, /* quad */ "ERROR: unsupported face type"); fac->type = eleptr [0]; for (n = 0; n < eleptr [0]; n ++) fac->nodes [n] = eleptr [n+1]; sort (fac->nodes, fac->nodes+fac->type-1); fac->color = eleptr [eleptr [0] + 1]; MAP_Insert (&mapmem, &smap, fac, /* map by the type/nodes key */ fac, face_compare); } /* set up nodes */ for (temp = minimal_node, node = msh->nodes; temp <= maximal_node; temp ++, node ++) { COPY (nodes [temp], *node); } /* set up faces */ for (fac = flist; fac; fac = fac->next) { if (fac->ele) /* see (***) */ { ele = fac->ele; cac = static_cast<FACE*>(MEM_Alloc (&msh->facmem)); setup_face (ele, fac->index, cac, 0); /* setup face nodes without sorting them */ cac->index = fac->index; cac->ele = fac->ele; setup_normal (msh->nodes, cac); /* calculate outer spatial normal */ cac->next = ele->faces; /* append element face list */ ele->faces = cac; /* set the mapped surface kind if possible => otherwise the global one */ gac = static_cast<FACE*>(MAP_Find (smap, fac, face_compare)); cac->color = (gac ? gac->color : surfaces [0]); } } /* create mesh face list */ for (ele = msh->surfeles; ele; ele = ele->next) { for (fac = ele->faces; fac; fac = fac->next) { fac->n = msh->faces; msh->faces = fac; } } /* clean up */ MEM_Release (&facmem); MEM_Release (&mapmem); return msh; }
int main(int argc, char** argv) { char buf[BUFSIZ]; struct font_glyph_desc desc; struct font_system* sys = NULL; struct font_rsrc* font = NULL; struct font_glyph* glyph = NULL; const char* path = NULL; unsigned char* buffer = NULL; size_t buffer_size = 0; int h = 0; int w = 0; int Bpp = 0; int i = 0; bool b = false; if(argc != 2) { printf("usage: %s FONT\n", argv[0]); goto error; } path = argv[1]; CHECK(font_system_create( NULL, NULL ), BAD_ARG); CHECK(font_system_create(NULL, &sys), OK); CHECK(font_rsrc_create(NULL, NULL, NULL), BAD_ARG); CHECK(font_rsrc_create(sys, NULL, NULL), BAD_ARG); CHECK(font_rsrc_create(NULL, NULL, &font), BAD_ARG); CHECK(font_rsrc_create(sys, NULL, &font), OK); CHECK(font_rsrc_load(NULL, NULL), BAD_ARG); CHECK(font_rsrc_load(font, NULL), BAD_ARG); CHECK(font_rsrc_load(NULL, path), BAD_ARG); CHECK(font_rsrc_load(font, path), OK); CHECK(font_rsrc_is_scalable(NULL, NULL), BAD_ARG); CHECK(font_rsrc_is_scalable(font, NULL), BAD_ARG); CHECK(font_rsrc_is_scalable(NULL, &b), BAD_ARG); CHECK(font_rsrc_is_scalable(font, &b), OK); if(b) { CHECK(font_rsrc_set_size(NULL, 0, 0), BAD_ARG); CHECK(font_rsrc_set_size(font, 0, 0), BAD_ARG); CHECK(font_rsrc_set_size(NULL, 32, 0), BAD_ARG); CHECK(font_rsrc_set_size(font, 32, 0), BAD_ARG); CHECK(font_rsrc_set_size(NULL, 0, 64), BAD_ARG); CHECK(font_rsrc_set_size(font, 0, 64), BAD_ARG); CHECK(font_rsrc_set_size(NULL, 32, 64), BAD_ARG); CHECK(font_rsrc_set_size(font, 32, 64), OK); CHECK(font_rsrc_set_size(font, 16, 16), OK); } CHECK(font_rsrc_get_line_space(NULL, NULL), BAD_ARG); CHECK(font_rsrc_get_line_space(font, NULL), BAD_ARG); CHECK(font_rsrc_get_line_space(NULL, &i), BAD_ARG); CHECK(font_rsrc_get_line_space(font, &i), OK); CHECK(font_rsrc_get_glyph(NULL, L'a', NULL), BAD_ARG); CHECK(font_rsrc_get_glyph(font, L'a', NULL), BAD_ARG); CHECK(font_rsrc_get_glyph(NULL, L'a', &glyph), BAD_ARG); CHECK(font_rsrc_get_glyph(font, L'a', &glyph), OK); CHECK(font_glyph_get_desc(NULL, NULL), BAD_ARG); CHECK(font_glyph_get_desc(glyph, NULL), BAD_ARG); CHECK(font_glyph_get_desc(NULL, &desc), BAD_ARG); CHECK(font_glyph_get_desc(glyph, &desc), OK); CHECK(desc.character, L'a'); CHECK(font_glyph_get_bitmap(NULL, true, NULL, NULL, NULL, NULL), BAD_ARG); CHECK(font_glyph_get_bitmap(glyph, true, NULL, NULL, NULL, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, &w, NULL, NULL, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, NULL, &h, NULL, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, &w, &h, NULL, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, NULL, NULL, &Bpp, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, &w, NULL, &Bpp, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, NULL, &h, &Bpp, NULL), OK); CHECK(font_glyph_get_bitmap(glyph, true, &w, &h, &Bpp, NULL), OK); NCHECK(w, 0); NCHECK(h, 0); NCHECK(Bpp, 0); buffer = MEM_CALLOC (&mem_default_allocator, (size_t)(w*h*Bpp), sizeof(unsigned char)); NCHECK(buffer, NULL); buffer_size = (size_t)(w*h*Bpp) * sizeof(unsigned char); CHECK(font_glyph_get_bitmap(glyph, false, NULL, NULL, NULL, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, &w, NULL, NULL, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, NULL, &h, NULL, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, &w, &h, NULL, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, NULL, NULL, &Bpp, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, &w, NULL, &Bpp, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, NULL, &h, &Bpp, buffer), OK); CHECK(font_glyph_get_bitmap(glyph, false, &w, &h, &Bpp, buffer), OK); CHECK(font_glyph_ref_get(NULL), BAD_ARG); CHECK(font_glyph_ref_get(glyph), OK); CHECK(font_glyph_ref_put(NULL), BAD_ARG); CHECK(font_glyph_ref_put(glyph), OK); CHECK(font_glyph_ref_put(glyph), OK); b = true; for(i = 0; b && i < w*h*Bpp; ++i) b = ((int)buffer[i] == 0); CHECK(b, false); for(i = 32; i < 127; ++i) { size_t required_buffer_size = 0; CHECK(font_rsrc_get_glyph(font, (wchar_t)i, &glyph), OK); CHECK(font_glyph_get_bitmap(glyph, true, &w, &h, &Bpp, NULL), OK); required_buffer_size = (size_t)(w * h * Bpp) * sizeof(unsigned char); if(required_buffer_size > buffer_size) { buffer = MEM_REALLOC(&mem_default_allocator,buffer, required_buffer_size); NCHECK(buffer, NULL); buffer_size = required_buffer_size; } CHECK(font_glyph_get_bitmap(glyph, true, &w, &h, &Bpp, buffer), OK); NCHECK(snprintf(buf, BUFSIZ, "/tmp/%.3d.ppm", i - 32), BUFSIZ); CHECK(image_ppm_write(buf, w, h, Bpp, buffer), 0); CHECK(font_glyph_ref_put(glyph), OK); } MEM_FREE(&mem_default_allocator, buffer); CHECK(font_rsrc_ref_get(NULL), BAD_ARG); CHECK(font_rsrc_ref_get(font), OK); CHECK(font_rsrc_ref_put(NULL), BAD_ARG); CHECK(font_rsrc_ref_put(font), OK); CHECK(font_rsrc_ref_put(font), OK); CHECK(font_system_ref_get(NULL), BAD_ARG); CHECK(font_system_ref_get(sys), OK); CHECK(font_system_ref_put(NULL), BAD_ARG); CHECK(font_system_ref_put(sys), OK); CHECK(font_system_ref_put(sys), OK); CHECK(MEM_ALLOCATED_SIZE(&mem_default_allocator), 0); return 0; error: return -1; }
/* communicate integers and doubles using point to point communication */ int COM (MPI_Comm comm, int tag, COMDATA *send, int nsend, COMDATA **recv, int *nrecv) /* recv is contiguous => free (*recv) releases all memory */ { COMDATA *cd; int rank, ncpu, send_size, (*send_sizes) [3], *send_position, *send_rank, send_count, *send_rank_all, *send_count_all, *send_rank_disp, *recv_rank, (*recv_sizes) [3], recv_count, i, j, k, l; char **send_data, **recv_data; MPI_Request *req; MPI_Status *sta; void *p; MPI_Comm_rank (comm, &rank); MPI_Comm_size (comm, &ncpu); ERRMEM (send_sizes = MEM_CALLOC (ncpu * sizeof (int [3]))); ERRMEM (send_position = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (send_rank = malloc (ncpu * sizeof (int))); ERRMEM (send_data = malloc (ncpu * sizeof (char*))); /* compute send sizes */ for (i = 0, cd = send; i < nsend; i ++, cd ++) { send_sizes [cd->rank][0] += cd->ints; send_sizes [cd->rank][1] += cd->doubles; MPI_Pack_size (cd->ints, MPI_INT, comm, &j); MPI_Pack_size (cd->doubles, MPI_DOUBLE, comm, &k); send_sizes [cd->rank][2] += (j + k); } /* allocate send buffers */ for (send_size = i = 0; i < ncpu; i ++) { if (send_sizes [i][2]) { ERRMEM (send_data [i] = malloc (send_sizes [i][2])); send_position [i] = 0; send_size += send_sizes [i][2]; } } /* pack ints */ for (i = 0, cd = send; i < nsend; i ++, cd ++) { if (cd->ints) { MPI_Pack (cd->i, cd->ints, MPI_INT, send_data [cd->rank], send_sizes [cd->rank][2], &send_position [cd->rank], comm); } } /* pack doubles */ for (i = 0, cd = send; i < nsend; i ++, cd ++) { if (cd->doubles) { MPI_Pack (cd->d, cd->doubles, MPI_DOUBLE, send_data [cd->rank], send_sizes [cd->rank][2], &send_position [cd->rank], comm); } } #if DEBUG for (i = 0; i < ncpu; i ++) { ASSERT_DEBUG (send_position [i] <= send_sizes [i][2], "Incorrect packing"); } #endif /* compute send ranks and move data */ for (send_count = i = 0; i < ncpu; i ++) { if (send_sizes [i][2]) { send_rank [send_count] = i; send_data [send_count] = send_data [i]; send_sizes [send_count][0] = send_sizes [i][0]; send_sizes [send_count][1] = send_sizes [i][1]; send_sizes [send_count][2] = send_sizes [i][2]; send_count ++; } } ERRMEM (send_count_all = malloc (ncpu * sizeof (int))); ERRMEM (recv_rank = malloc (ncpu * sizeof (int))); /* gather all send ranks */ MPI_Allgather (&send_count, 1, MPI_INT, send_count_all, 1, MPI_INT, comm); ERRMEM (send_rank_disp = malloc (ncpu * sizeof (int))); for (send_rank_disp [0] = l = i = 0; i < ncpu; i ++) { l += send_count_all [i]; if (i < ncpu-1) send_rank_disp [i+1] = l; } ERRMEM (send_rank_all = malloc (l * sizeof (int))); MPI_Allgatherv (send_rank, send_count, MPI_INT, send_rank_all, send_count_all, send_rank_disp, MPI_INT, comm); /* compute receive ranks */ for (recv_count = k = i = 0; i < l; i += send_count_all [k], k ++) { for (j = 0; j < send_count_all [k]; j ++) { if (send_rank_all [i+j] == rank) /* 'k'th rank is sending here */ { recv_rank [recv_count] = k; recv_count ++; break; } } } ERRMEM (recv_sizes = malloc (recv_count * sizeof (int [3]))); ERRMEM (req = malloc (recv_count * sizeof (MPI_Request))); ERRMEM (sta = malloc (recv_count * sizeof (MPI_Status))); /* communicate receive sizes */ for (i = 0; i < recv_count; i ++) { MPI_Irecv (recv_sizes [i], 3, MPI_INT, recv_rank [i], tag, comm, &req [i]); } MPI_Barrier (comm); for (i = 0; i < send_count; i ++) { MPI_Rsend (send_sizes [i], 3, MPI_INT, send_rank [i], tag, comm); } MPI_Waitall (recv_count, req, sta); /* contiguous receive size */ j = recv_count * sizeof (COMDATA); for (i = 0; i < recv_count; i ++) { j += recv_sizes [i][0] * sizeof (int) + recv_sizes [i][1] * sizeof (double); } /* prepare receive buffers */ ERRMEM (recv_data = malloc (recv_count * sizeof (char*))); ERRMEM ((*recv) = malloc (j)); p = (*recv) + recv_count; *nrecv = recv_count; for (i = 0, cd = *recv; i < recv_count; i ++, cd ++) { cd->rank = recv_rank [i]; cd->ints = recv_sizes [i][0]; cd->doubles = recv_sizes [i][1]; cd->i = p; p = (cd->i + cd->ints); cd->d = p; p = (cd->d + cd->doubles); ERRMEM (recv_data [i] = malloc (recv_sizes [i][2])); } /* communicate data */ for (i = 0; i < recv_count; i ++) { MPI_Irecv (recv_data [i], recv_sizes [i][2], MPI_PACKED, recv_rank [i], tag, comm, &req [i]); } MPI_Barrier (comm); for (i = 0; i < send_count; i ++) { MPI_Rsend (send_data [i], send_sizes [i][2], MPI_PACKED, send_rank [i], tag, comm); } MPI_Waitall (recv_count, req, sta); /* unpack data */ for (i = j = 0; i < recv_count; i ++, j = 0) { MPI_Unpack (recv_data [i], recv_sizes [i][2], &j, (*recv) [i].i, (*recv) [i].ints, MPI_INT, comm); MPI_Unpack (recv_data [i], recv_sizes [i][2], &j, (*recv) [i].d, (*recv) [i].doubles, MPI_DOUBLE, comm); } /* cleanup */ free (send_rank_disp); free (send_sizes); free (send_position); free (send_rank); for (i = 0; i < send_count; i ++) free (send_data [i]); free (send_data); free (send_count_all); free (send_rank_all); free (recv_rank); free (recv_sizes); for (i = 0; i < recv_count; i ++) free (recv_data [i]); free (recv_data); free (req); free (sta); return send_size; }
/* create a repetitive point to point communication pattern; * ranks and sizes must not change during the communication; * pointers to send and receive buffers data must not change */ void* COM_Pattern (MPI_Comm comm, int tag, COMDATA *send, int nsend, COMDATA **recv, int *nrecv) /* recv is contiguous => free (*recv) releases all memory */ { COMPATTERN *pattern; COMDATA *cd; int rank, ncpu, *send_rank_all, *send_count_all, *send_rank_disp, i, j, k, l; void *p; MPI_Comm_rank (comm, &rank); MPI_Comm_size (comm, &ncpu); ERRMEM (pattern = malloc (sizeof (COMPATTERN))); ERRMEM (pattern->rankmap = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (pattern->send_sizes = MEM_CALLOC (ncpu * sizeof (int [3]))); ERRMEM (pattern->send_position = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (pattern->send_rank = malloc (ncpu * sizeof (int))); ERRMEM (pattern->send_data = malloc (ncpu * sizeof (char*))); pattern->nsend = nsend; pattern->send = send; pattern->comm = comm; pattern->tag = tag; /* compute send sizes */ for (i = 0, cd = send; i < nsend; i ++, cd ++) { pattern->send_sizes [cd->rank][0] += cd->ints; pattern->send_sizes [cd->rank][1] += cd->doubles; MPI_Pack_size (cd->ints, MPI_INT, comm, &j); MPI_Pack_size (cd->doubles, MPI_DOUBLE, comm, &k); pattern->send_sizes [cd->rank][2] += (j + k); } /* allocate send buffers and prepare rank map */ for (pattern->send_size = i = j = 0; i < ncpu; i ++) { if (pattern->send_sizes [i][2]) { ERRMEM (pattern->send_data [i] = malloc (pattern->send_sizes [i][2])); pattern->rankmap [i] = j; pattern->send_size += pattern->send_sizes [i][2]; j ++; } } /* compute send ranks and move data */ for (pattern->send_count = i = 0; i < ncpu; i ++) { if (pattern->send_sizes [i][2]) { pattern->send_rank [pattern->send_count] = i; pattern->send_data [pattern->send_count] = pattern->send_data [i]; pattern->send_sizes [pattern->send_count][0] = pattern->send_sizes [i][0]; pattern->send_sizes [pattern->send_count][1] = pattern->send_sizes [i][1]; pattern->send_sizes [pattern->send_count][2] = pattern->send_sizes [i][2]; pattern->send_count ++; } } ERRMEM (send_count_all = malloc (ncpu * sizeof (int))); ERRMEM (pattern->recv_rank = malloc (ncpu * sizeof (int))); /* gather all send ranks */ MPI_Allgather (&pattern->send_count, 1, MPI_INT, send_count_all, 1, MPI_INT, comm); ERRMEM (send_rank_disp = malloc (ncpu * sizeof (int))); for (send_rank_disp [0] = l = i = 0; i < ncpu; i ++) { l += send_count_all [i]; if (i < ncpu-1) send_rank_disp [i+1] = l; } ERRMEM (send_rank_all = malloc (l * sizeof (int))); MPI_Allgatherv (pattern->send_rank, pattern->send_count, MPI_INT, send_rank_all, send_count_all, send_rank_disp, MPI_INT, comm); /* compute receive ranks */ for (pattern->recv_count = k = i = 0; i < l; i += send_count_all [k], k ++) { for (j = 0; j < send_count_all [k]; j ++) { if (send_rank_all [i+j] == rank) /* 'k'th rank is sending here */ { pattern->recv_rank [pattern->recv_count] = k; pattern->recv_count ++; break; } } } ERRMEM (pattern->recv_sizes = malloc (pattern->recv_count * sizeof (int [3]))); ERRMEM (pattern->recv_req = malloc (pattern->recv_count * sizeof (MPI_Request))); ERRMEM (pattern->recv_sta = malloc (pattern->recv_count * sizeof (MPI_Status))); ERRMEM (pattern->send_req = malloc (pattern->send_count * sizeof (MPI_Request))); ERRMEM (pattern->send_sta = malloc (pattern->send_count * sizeof (MPI_Status))); /* communicate receive sizes */ for (i = 0; i < pattern->recv_count; i ++) { MPI_Irecv (pattern->recv_sizes [i], 3, MPI_INT, pattern->recv_rank [i], tag, comm, &pattern->recv_req [i]); } MPI_Barrier (comm); for (i = 0; i < pattern->send_count; i ++) { MPI_Rsend (pattern->send_sizes [i], 3, MPI_INT, pattern->send_rank [i], tag, comm); } MPI_Waitall (pattern->recv_count, pattern->recv_req, pattern->recv_sta); /* contiguous receive size */ j = pattern->recv_count * sizeof (COMDATA); for (i = 0; i < pattern->recv_count; i ++) { j += pattern->recv_sizes [i][0] * sizeof (int) + pattern->recv_sizes [i][1] * sizeof (double); } /* prepare receive buffers */ ERRMEM (pattern->recv_data = malloc (pattern->recv_count * sizeof (char*))); ERRMEM (pattern->recv = malloc (j)); p = pattern->recv + pattern->recv_count; pattern->nrecv = pattern->recv_count; for (i = 0, cd = pattern->recv; i < pattern->recv_count; i ++, cd ++) { cd->rank = pattern->recv_rank [i]; cd->ints = pattern->recv_sizes [i][0]; cd->doubles = pattern->recv_sizes [i][1]; cd->i = p; p = (cd->i + cd->ints); cd->d = p; p = (cd->d + cd->doubles); ERRMEM (pattern->recv_data [i] = malloc (pattern->recv_sizes [i][2])); } /* truncate */ if (pattern->send_count) { ERRMEM (pattern->send_sizes = realloc (pattern->send_sizes, pattern->send_count * sizeof (int [3]))); ERRMEM (pattern->send_position = realloc (pattern->send_position, pattern->send_count * sizeof (int))); ERRMEM (pattern->send_rank = realloc (pattern->send_rank, pattern->send_count * sizeof (int))); ERRMEM (pattern->send_data = realloc (pattern->send_data, pattern->send_count * sizeof (char*))); } if (pattern->recv_count) ERRMEM (pattern->recv_rank = realloc (pattern->recv_rank, pattern->recv_count * sizeof (int))); /* cleanup */ free (send_rank_disp); free (send_count_all); free (send_rank_all); /* output */ *nrecv = pattern->nrecv; *recv = pattern->recv; return pattern; }
static int get_active_uniform (struct rb_context* ctxt, struct rb_program* program, GLuint index, GLsizei bufsize, GLchar* buffer, struct rb_uniform** out_uniform) { struct rb_uniform* uniform = NULL; GLsizei uniform_namelen = 0; GLint uniform_size = 0; GLenum uniform_type; int err = 0; if(!ctxt || !program || !out_uniform || bufsize < 0 || (bufsize && !buffer)) goto error; OGL(GetActiveUniform (program->name, index, bufsize, &uniform_namelen, &uniform_size, &uniform_type, buffer)); uniform = MEM_CALLOC(ctxt->allocator, 1, sizeof(struct rb_uniform)); if(!uniform) goto error; ref_init(&uniform->ref); RB(context_ref_get(ctxt)); uniform->ctxt = ctxt; RB(program_ref_get(program)); uniform->program = program; uniform->index = index; uniform->type = uniform_type; uniform->set = get_uniform_setter(uniform_type); if(buffer) { /* Add 1 to namelen <=> include the null character. */ ++uniform_namelen; uniform->name = MEM_ALLOC (ctxt->allocator, sizeof(char) * uniform_namelen); if(!uniform->name) goto error; uniform->name = strncpy(uniform->name, buffer, uniform_namelen); uniform->location = OGL(GetUniformLocation(program->name, uniform->name)); } exit: *out_uniform = uniform; return err; error: if(uniform) { RB(uniform_ref_put(uniform)); uniform = NULL; } err = -1; goto exit; }
/* create a repetitive all to all communication pattern; * ranks and sizes must not change during the communication; * pointers to send and receive buffers data must not change */ void* COMALL_Pattern (MPI_Comm comm, COMDATA *send, int nsend, COMDATA **recv, int *nrecv) /* recv is contiguous => free (*recv) releases all memory */ { COMALLPATTERN *pattern; COMDATA *cd; int rank, ncpu, i, j, k; void *p; MPI_Comm_rank (comm, &rank); MPI_Comm_size (comm, &ncpu); ERRMEM (pattern = MEM_CALLOC (sizeof (COMALLPATTERN))); ERRMEM (pattern->send_sizes = MEM_CALLOC (ncpu * sizeof (int [3]))); ERRMEM (pattern->send_counts = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (pattern->send_disps = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (pattern->send_position = MEM_CALLOC (ncpu * sizeof (int))); pattern->ncpu = ncpu; pattern->comm = comm; pattern->send = send; pattern->nsend = nsend; /* compute send sizes */ for (i = 0, cd = send; i < nsend; i ++, cd ++) { pattern->send_sizes [cd->rank][0] += cd->ints; pattern->send_sizes [cd->rank][1] += cd->doubles; MPI_Pack_size (cd->ints, MPI_INT, comm, &j); MPI_Pack_size (cd->doubles, MPI_DOUBLE, comm, &k); pattern->send_sizes [cd->rank][2] += (j + k); } /* compute send displacements */ for (pattern->send_size = i = 0; i < ncpu; i ++) { pattern->send_counts [i] = pattern->send_sizes [i][2]; pattern->send_size += pattern->send_counts [i]; if (i < (ncpu - 1)) pattern->send_disps [i+1] = pattern->send_size; } pattern->send_disps [0] = 0; /* allocate send buffer */ ERRMEM (pattern->send_data = malloc (pattern->send_size)); ERRMEM (pattern->recv_sizes = MEM_CALLOC (ncpu * sizeof (int [3]))); ERRMEM (pattern->recv_counts = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (pattern->recv_disps = MEM_CALLOC (ncpu * sizeof (int))); ERRMEM (pattern->recv_position = MEM_CALLOC (ncpu * sizeof (int))); /* distribute send sizes into receive sizes */ MPI_Alltoall (pattern->send_sizes, 3, MPI_INT, pattern->recv_sizes, 3, MPI_INT, comm); /* compute receive displacements */ for (pattern->recv_size = i = 0; i < ncpu; i ++) { pattern->recv_counts [i] = pattern->recv_sizes [i][2]; pattern->recv_size += pattern->recv_counts [i]; if (i < (ncpu - 1)) pattern->recv_disps [i+1] = pattern->recv_size; } pattern->recv_disps [0] = 0; /* allocate receive buffer */ ERRMEM (pattern->recv_data = malloc (pattern->recv_size)); if (pattern->recv_size) { /* contiguous receive size */ j = ncpu * sizeof (COMDATA); for (i = 0; i < ncpu; i ++) { j += pattern->recv_sizes [i][0] * sizeof (int) + pattern->recv_sizes [i][1] * sizeof (double); } /* prepare output receive data */ ERRMEM (pattern->recv = malloc (j)); ERRMEM ((*recv) = malloc (j)); p = (*recv) + ncpu; for (i = 0, cd = *recv; i < ncpu; i ++, cd ++) { cd->rank = i; cd->ints = pattern->recv_sizes [i][0]; cd->doubles = pattern->recv_sizes [i][1]; cd->i = p; p = (cd->i + cd->ints); cd->d = p; p = (cd->d + cd->doubles); pattern->recv [i] = *cd; } /* compress receive storage */ for (*nrecv = i = 0; i < ncpu; i ++) { if (pattern->recv_counts [i]) { (*recv) [*nrecv] = (*recv) [i]; (*nrecv) ++; } } } else { *recv = NULL; *nrecv = 0; } return pattern; }