// **TODO**: Add an test. This function shows only the usage of `append_cb`. static char * test_single() { mpz_t a, b; mpz_array array1, array2, array_expect; mpz_pool pool; pool_init(&pool, 0); array_init(&array1, 3); array_init(&array2, 3); array_init(&array_expect, 3); // primes: 577, 727, 863 mpz_init_set_str(a, "577", 10); array_add(&array_expect, a); mpz_set_str(a, "727", 10); array_add(&array_expect, a); mpz_set_str(a, "863", 10); array_add(&array_expect, a); // `a = 727 * 577 = 419479` // `b = 727 * 863 = 627401` mpz_set_str(a, "419479", 10); mpz_init_set_str(b, "627401", 10); append_cb(&pool, &array1, a, b); if (mpz_cmp_ui(a, 419479) != 0) { return "append_cb has changed the input value a!"; } if (mpz_cmp_ui(b, 627401) != 0) { return "append_cb has changed the input value b!"; } array_msort(&array1); if (!array_equal(&array_expect, &array1)) { return "array1 and array_expect differ!"; } append_cb(&pool, &array2, b, a); if (mpz_cmp_ui(a, 419479) != 0) { return "append_cb has changed the input value a!"; } if (mpz_cmp_ui(b, 627401) != 0) { return "append_cb has changed the input value b!"; } array_msort(&array2); if (!array_equal(&array_expect, &array2)) { return "array2 and array_expect differ!"; } mpz_clear(a); mpz_clear(b); array_clear(&array1); array_clear(&array2); array_clear(&array_expect); pool_clear(&pool); return 0; }
// **TODO**: Add an test. This function shows only the usage of `append_cb`. static char * test_multiple() { mpz_t a, b; mpz_array array1, array2, array_expect; mpz_pool pool; pool_init(&pool, 0); array_init(&array1, 3); array_init(&array2, 3); array_init(&array_expect, 3); // `30997 = 139 * 223` // `627401 = 727 * 863` // `182909 = 317 * 577` mpz_init_set_str(a, "30997", 10); array_add(&array_expect, a); mpz_set_str(a, "182909", 10); array_add(&array_expect, a); mpz_set_str(a, "627401", 10); array_add(&array_expect, a); // primes: 139, 223, 317, 577, 727, 863 // `a = 139 * 223 * 317 * 577 = 5669630273` // `b = 317 * 577 * 727 * 863 = 114757289509` mpz_set_str(a, "5669630273", 10); mpz_init_set_str(b, "114757289509", 10); append_cb(&pool, &array1, a, b); array_msort(&array1); if (!array_equal(&array_expect, &array1)) { return "array1 and array_expect differ!"; } append_cb(&pool, &array2, b, a); array_msort(&array2); if (!array_equal(&array_expect, &array2)) { return "array2 and array_expect differ!"; } mpz_clear(a); mpz_clear(b); array_clear(&array1); array_clear(&array2); array_clear(&array_expect); pool_clear(&pool); return 0; }
sfpr_list_node_t *sfpr_list_append_with_cb(sfpr_list_t *list,void(*append_cb)(void*data, void* param),void* param,void *data) { int len = 0; sfpr_list_node_t *node = NULL; if(list->pool){ node = (sfpr_list_node_t *)sfpr_mem_malloc(list->pool,sizeof(sfpr_list_node_t)); /**< 申请链表节点存放数据*/ }else{ node = (sfpr_list_node_t *)malloc(sizeof(sfpr_list_node_t)); /**< 申请链表节点存放数据*/ } if (!node) { fprintf(stderr,"malloc failed!"); return NULL; } node->data = data; sfpr_mutex_lock(&list->mutex); if (list->head == NULL) /**< 链表为空,插入表头*/ { list->head = node; list->tail = node; } else { list->tail->next = node; list->tail = list->tail->next; } if(append_cb) append_cb(data, param); list->count++; list->tail->next = NULL; sfpr_mutex_unlock(&list->mutex); return node; }
// This algorithm finds cb(P∪{b}) when P is coprime. // // Algorithm 16.2 [PDF page 21](http://cr.yp.to/lineartime/dcba-20040404.pdf) // // See [cbextend test](test-cbextend.html) for basic usage. void cbextend(mpz_array *ret, mpz_array *p, const mpz_t b) { size_t i; mpz_t x, a, r; mpz_array s; // **Sep 1** // // If P = {}: Print b if b != 1. Stop. if (!p->used) { if (mpz_cmp_ui(b, 1) != 0) { array_add(ret, b); } } // **Sep 2** // // Compute x ← prod P mpz_init(x); array_prod(p, x); // **Sep 3** // // Compute (a,r) ← (ppi,ppo)(b, x) b mpz_init(a); mpz_init(r); ppi_ppo(a, r, b, x); // **Sep 4** // // Print r if r != 1. if (mpz_cmp_ui(r, 1) != 0) { array_add(ret, r); } // **Sep 5** // // Compute S ← split(a,P) array_init(&s, p->used); array_split(&s, a, p); // **Sep 6** // // For each (p, c) ∈ S: Apply append_cb(p, c). if (p->used != s.used) { fprintf(stderr, "logic error in cbextend: p.used != s.used"); } else { for (i = 0; i < p->used; i++) { append_cb(ret, p->array[i], s.array[i]); } } // Free the memory. array_clear(&s); mpz_clear(a); mpz_clear(r); mpz_clear(x); }
// Algorithm 13.2 [PDF page 17](http://cr.yp.to/lineartime/dcba-20040404.pdf) // // See [appendcb test](test-appendcb.html) for basic usage. void append_cb(mpz_array *out, const mpz_t a, const mpz_t b) { mpz_t r, g, h, c, c0, x, y, d, b1, b2, a1; unsigned long long n; /* gmp_printf("enter append_cb(%Zd, %Zd)\n", a, b); */ // **Step 1** // // If `b == 1` and `a == 1` add `a` to the array. If `b == 1` return. // This is the break condition of the recursive function. if (mpz_cmp_ui(b, 1) == 0) { if (mpz_cmp_ui(a, 1) != 0) { array_add(out, a); } return; } mpz_init(r); mpz_init(g); mpz_init(a1); // **Step 2** // // Store ppi in `a1` and ppo in `r`. Use `a1` and not `a` to keep the input `const` // and handle the case that one parameter is used twice. ppi_ppo(a1, r, a, b); // **Step 3** // // If `r` (ppo) is **not** one add it to the array. if (mpz_cmp_ui(r, 1) != 0) { array_add(out, r); } mpz_init(h); mpz_init(c); // **Step 4** // // Caluclate the gcd, ppg and pple. gcd_ppg_pple(g, h, c, a1, b); // **Step 5** // // Store pple in `c0` and `x`. mpz_init_set(c0, c); mpz_init_set(x, c0); // **Step 6** // // Set `n` to one. n = 1; mpz_init(b1); mpz_init(b2); mpz_init(d); mpz_init(y); // Start while loop to be able to return to step 7. while(1) { // **Step 7** // // Compute (g, h, c) ← (gcd,ppg,pple)(h,g^2) mpz_mul(b1, g, g); mpz_set(b2, h); gcd_ppg_pple(g, h, c, b2, b1); // **Step 8** // // Compute d ← gcd(c, b) mpz_gcd(d, c, b); // **Step 9** // // Set x ← xd mpz_mul(x, x, d); // **Sep 10** // // Compute y ← d^2^ n−1. mpz_set(y, d); two_power(y, n - 1); // **Sep 11** // // Recursively apply (c/y,d). mpz_fdiv_q(b1, c, y); /* gmp_printf("rec call append_cb(%Zd, %Zd)\n", b1, d); */ append_cb(out, b1, d); // **Sep 12** // // If h is not 1: Set n ← n+1. Return to Step 7. if (mpz_cmp_ui(h, 1) == 0) break; n = n + 1; } // **Step 13** // // Recursively apply (b/x, c0). mpz_fdiv_q(b1, b, x); append_cb(out, b1, c0); // Free the memory. mpz_clear(r); mpz_clear(g); mpz_clear(h); mpz_clear(c); mpz_clear(c0); mpz_clear(x); mpz_clear(y); mpz_clear(d); mpz_clear(b1); mpz_clear(b2); mpz_clear(a1); }
/*------------------------------------------------------------------------- * Function: H5DOappend() * * Purpose: To append elements to a dataset. * * axis: the dataset dimension (zero-based) for the append * extension: the # of elements to append for the axis-th dimension * memtype: the datatype * buf: buffer with data for the append * * Return: Non-negative on success/Negative on failure * * Programmer: Vailin Choi; Jan 2014 * * Note: * This routine is copied from the fast forward feature branch: features/hdf5_ff * src/H5FF.c:H5DOappend() with the following modifications: * 1) Remove and replace macro calls such as * FUNC_ENTER_API, H5TRACE, HGOTO_ERROR * accordingly because hl does not have these macros * 2) Replace H5I_get_type() by H5Iget_type() * 3) Replace H5P_isa_class() by H5Pisa_class() * 4) Fix a bug in the following: replace extension by size[axis] * if(extension < old_size) { * ret_value = FAIL; * goto done; * } * *------------------------------------------------------------------------- */ herr_t H5DOappend(hid_t dset_id, hid_t dxpl_id, unsigned axis, size_t extension, hid_t memtype, const void *buf) { hbool_t created_dxpl = FALSE; /* Whether we created a DXPL */ hsize_t size[H5S_MAX_RANK]; /* The new size (after extension */ hsize_t old_size = 0; /* The size of the dimension to be extended */ int sndims; /* Number of dimensions in dataspace (signed) */ unsigned ndims; /* Number of dimensions in dataspace */ hid_t space_id = FAIL; /* Old file space */ hid_t new_space_id = FAIL; /* New file space (after extension) */ hid_t mem_space_id = FAIL; /* Memory space for data buffer */ hssize_t snelmts; /* Number of elements in selection (signed) */ hsize_t nelmts; /* Number of elements in selection */ hid_t dapl = FAIL; /* Dataset access property list */ hsize_t start[H5S_MAX_RANK]; /* H5Sselect_Hyperslab: starting offset */ hsize_t count[H5S_MAX_RANK]; /* H5Sselect_hyperslab: # of blocks to select */ hsize_t stride[H5S_MAX_RANK]; /* H5Sselect_hyperslab: # of elements to move when selecting */ hsize_t block[H5S_MAX_RANK]; /* H5Sselect_hyperslab: # of elements in a block */ hsize_t *boundary = NULL; /* Boundary set in append flush property */ H5D_append_cb_t append_cb; /* Callback function set in append flush property */ void *udata; /* User data set in append flush property */ hbool_t hit = FALSE; /* Boundary is hit or not */ hsize_t k; /* Local index variable */ unsigned u; /* Local index variable */ herr_t ret_value = FAIL; /* Return value */ /* check arguments */ if(H5I_DATASET != H5Iget_type(dset_id)) goto done; /* If the user passed in a default DXPL, create one to pass to H5Dwrite() */ if(H5P_DEFAULT == dxpl_id) { if((dxpl_id = H5Pcreate(H5P_DATASET_XFER)) < 0) goto done; created_dxpl = TRUE; } /* end if */ else if(TRUE != H5Pisa_class(dxpl_id, H5P_DATASET_XFER)) goto done; /* Get the dataspace of the dataset */ if(FAIL == (space_id = H5Dget_space(dset_id))) goto done; /* Get the rank of this dataspace */ if((sndims = H5Sget_simple_extent_ndims(space_id)) < 0) goto done; ndims = (unsigned)sndims; /* Verify correct axis */ if(axis >= ndims) goto done; /* Get the dimensions sizes of the dataspace */ if(H5Sget_simple_extent_dims(space_id, size, NULL) < 0) goto done; /* Adjust the dimension size of the requested dimension, * but first record the old dimension size */ old_size = size[axis]; size[axis] += extension; if(size[axis] < old_size) goto done; /* Set the extent of the dataset to the new dimension */ if(H5Dset_extent(dset_id, size) < 0) goto done; /* Get the new dataspace of the dataset */ if(FAIL == (new_space_id = H5Dget_space(dset_id))) goto done; /* Select a hyperslab corresponding to the append operation */ for(u = 0 ; u < ndims ; u++) { start[u] = 0; stride[u] = 1; count[u] = size[u]; block[u] = 1; if(u == axis) { count[u] = extension; start[u] = old_size; } /* end if */ } /* end for */ if(FAIL == H5Sselect_hyperslab(new_space_id, H5S_SELECT_SET, start, stride, count, block)) goto done; /* The # of elemnts in the new extended dataspace */ if((snelmts = H5Sget_select_npoints(new_space_id)) < 0) goto done; nelmts = (hsize_t)snelmts; /* create a memory space */ if(FAIL == (mem_space_id = H5Screate_simple(1, &nelmts, NULL))) goto done; /* Write the data */ if(H5Dwrite(dset_id, memtype, mem_space_id, new_space_id, dxpl_id, buf) < 0) goto done; /* Obtain the dataset's access property list */ if((dapl = H5Dget_access_plist(dset_id)) < 0) goto done; /* Allocate the boundary array */ boundary = (hsize_t *)HDmalloc(ndims * sizeof(hsize_t)); /* Retrieve the append flush property */ if(H5Pget_append_flush(dapl, ndims, boundary, &append_cb, &udata) < 0) goto done; /* No boundary for this axis */ if(boundary[axis] != 0) { /* Determine whether a boundary is hit or not */ for(k = start[axis]; k < size[axis]; k++) if(!((k + 1) % boundary[axis])) { hit = TRUE; break; } if(hit) { /* Hit the boundary */ /* Invoke callback if there is one */ if(append_cb && append_cb(dset_id, size, udata) < 0) goto done; /* Do a dataset flush */ if(H5Dflush(dset_id) < 0) goto done; } /* end if */ } /* end if */ /* Indicate success */ ret_value = SUCCEED; done: /* Close dxpl if we created it vs. one was passed in */ if(created_dxpl) { if(H5Pclose(dxpl_id) < 0) ret_value = FAIL; } /* end if */ /* Close old dataspace */ if(space_id != FAIL && H5Sclose(space_id) < 0) ret_value = FAIL; /* Close new dataspace */ if(new_space_id != FAIL && H5Sclose(new_space_id) < 0) ret_value = FAIL; /* Close memory dataspace */ if(mem_space_id != FAIL && H5Sclose(mem_space_id) < 0) ret_value = FAIL; /* Close the dataset access property list */ if(dapl != FAIL && H5Pclose(dapl) < 0) ret_value = FAIL; if(boundary) HDfree(boundary); return ret_value; } /* H5DOappend() */