/* This definition is stupid. Think of something better */ SOCKET * NEW(socket) (SOCKET *sk, int type, int domain, int proto, char sr, unsigned int port, const char *hostname, void *ssl_ctx) { /* Object allocation */ iiprintf(SOCKET); SOCKET *s; socket_t *sock; /* Check memory */ if (!sk) { if (!(s = nalloc(sizeof(SOCKET), "socket.object"))) return NULL; if (!(sock = (socket_t *)nalloc(sizeof(socket_t), "socket.socket"))) { free(s); return NULL; } memset(sock, 0, sizeof(socket_t)); } else { s = sk; sock = sk->data; memset(sock, 0, sizeof(socket_t)); } /* All of this can be done with a macro */ sock->buffer = NULL; sock->connection_type = type; sock->domain = domain; sock->protocol = proto; sock->addrsize = sizeof(struct sockaddr); sock->bufsz = 1024; sock->opened = 0; sock->backlog = 500; sock->waittime = 5000; // 3000 microseconds sock->hostname = !hostname ? NULL : (char *)hostname; /* Check port number (clients are zero until a request is made) */ if (port < 0 || port > 65536) { /* Free allocated socket */ vvprintf("Invalid port specified."); return errnull("Invalid port specified."); } else if (!port) sock->port = 0; else sock->port = port; #if 0 /* Service check (part of struct in the future) */ fprintf(stderr, "Checking that port binds to a real service..."); if (!services[port]) sock->service = "UNKNOWN"; else sock->service = (char *)services[port]; #endif /* Set up the address data structure for use as either client or server */ sock->_class = sr; if (sock->_class == 's') { if ((sock->srvaddrinfo = (struct sockaddr_in *)nalloc(sizeof(struct sockaddr_in), "sockaddr.info")) == NULL) return errnull("Could not allocate structure specified."); /* Some type of gethosting must be done */ memset(sock->srvaddrinfo, 0, sizeof(struct sockaddr_in)); struct sockaddr_in *saa = sock->srvaddrinfo; saa->sin_family = AF_INET; saa->sin_port = htons(sock->port); /* A smart string function can decide whether or not this is IPv6 */ (&saa->sin_addr)->s_addr = htonl(INADDR_ANY); } else if (sock->_class == 'c') { /* Set up the addrinfo structure for a future client request. */ struct addrinfo *h; memset(&sock->hints, 0, sizeof(sock->hints)); h = &sock->hints; h->ai_family = sock->domain; h->ai_socktype = sock->connection_type; } #if 0 /* Show the buffer pointer... */ fprintf(stderr, "tcp socket buffer: %p (%s)\n", sock->buffer, sock->_class == 'c' ? "client" : \ sock->_class == 'd' ? "child" : "server"); #endif /* Set up an SSL context if asked. */ if (!ssl_ctx) sock->ssl_ctx = NULL; else sock->ssl_ctx = ssl_ctx; /* Finally, create a socket. */ sock->fd = socket(sock->domain, sock->connection_type, sock->protocol); sock->opened = 1; /* Set timeout, reusable bit and any other options */ struct timeval to; to.tv_sec = 2; to.tv_usec = 0; if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, &to, sizeof(to)) == -1) { // sock->free(sock); errsys("Could not reopen socket."); return NULL; } /* Set private data */ s->data = sock; /* Set the socket info as part of the object. */ s->data->urn = NULL; /* Set the URN to NULL */ /* The standard */ s->free = &__free; s->info = &__printf; /* The rest */ s->connect = &__connect; s->bind = &__bind; s->listen = &__listen; s->accept = &__accept; s->shutdown = &__shutdown; s->close = &__close; s->send = &__send; s->recv = &__recv; s->addrinfo = &__addrinfo; s->recvd = &recvd; s->parsed = &parsed; s->release = &__release; return INITIALIZED(s); }
/* Put in s an approximation of digamma(x). Assumes x >= 2. Assumes s does not overlap with x. Returns an integer e such that the error is bounded by 2^e ulps of the result s. */ static mpfr_exp_t mpfr_digamma_approx (mpfr_ptr s, mpfr_srcptr x) { mpfr_prec_t p = MPFR_PREC (s); mpfr_t t, u, invxx; mpfr_exp_t e, exps, f, expu; mpz_t *INITIALIZED(B); /* variable B declared as initialized */ unsigned long n0, n; /* number of allocated B[] */ MPFR_ASSERTN(MPFR_IS_POS(x) && (MPFR_EXP(x) >= 2)); mpfr_init2 (t, p); mpfr_init2 (u, p); mpfr_init2 (invxx, p); mpfr_log (s, x, MPFR_RNDN); /* error <= 1/2 ulp */ mpfr_ui_div (t, 1, x, MPFR_RNDN); /* error <= 1/2 ulp */ mpfr_div_2exp (t, t, 1, MPFR_RNDN); /* exact */ mpfr_sub (s, s, t, MPFR_RNDN); /* error <= 1/2 + 1/2*2^(EXP(olds)-EXP(s)) + 1/2*2^(EXP(t)-EXP(s)). For x >= 2, log(x) >= 2*(1/(2x)), thus olds >= 2t, and olds - t >= olds/2, thus 0 <= EXP(olds)-EXP(s) <= 1, and EXP(t)-EXP(s) <= 0, thus error <= 1/2 + 1/2*2 + 1/2 <= 2 ulps. */ e = 2; /* initial error */ mpfr_mul (invxx, x, x, MPFR_RNDZ); /* invxx = x^2 * (1 + theta) for |theta| <= 2^(-p) */ mpfr_ui_div (invxx, 1, invxx, MPFR_RNDU); /* invxx = 1/x^2 * (1 + theta)^2 */ /* in the following we note err=xxx when the ratio between the approximation and the exact result can be written (1 + theta)^xxx for |theta| <= 2^(-p), following Higham's method */ B = mpfr_bernoulli_internal ((mpz_t *) 0, 0); mpfr_set_ui (t, 1, MPFR_RNDN); /* err = 0 */ for (n = 1;; n++) { /* compute next Bernoulli number */ B = mpfr_bernoulli_internal (B, n); /* The main term is Bernoulli[2n]/(2n)/x^(2n) = B[n]/(2n+1)!(2n)/x^(2n) = B[n]*t[n]/(2n) where t[n]/t[n-1] = 1/(2n)/(2n+1)/x^2. */ mpfr_mul (t, t, invxx, MPFR_RNDU); /* err = err + 3 */ mpfr_div_ui (t, t, 2 * n, MPFR_RNDU); /* err = err + 1 */ mpfr_div_ui (t, t, 2 * n + 1, MPFR_RNDU); /* err = err + 1 */ /* we thus have err = 5n here */ mpfr_div_ui (u, t, 2 * n, MPFR_RNDU); /* err = 5n+1 */ mpfr_mul_z (u, u, B[n], MPFR_RNDU); /* err = 5n+2, and the absolute error is bounded by 10n+4 ulp(u) [Rule 11] */ /* if the terms 'u' are decreasing by a factor two at least, then the error coming from those is bounded by sum((10n+4)/2^n, n=1..infinity) = 24 */ exps = mpfr_get_exp (s); expu = mpfr_get_exp (u); if (expu < exps - (mpfr_exp_t) p) break; mpfr_sub (s, s, u, MPFR_RNDN); /* error <= 24 + n/2 */ if (mpfr_get_exp (s) < exps) e <<= exps - mpfr_get_exp (s); e ++; /* error in mpfr_sub */ f = 10 * n + 4; while (expu < exps) { f = (1 + f) / 2; expu ++; } e += f; /* total rouding error coming from 'u' term */ } n0 = ++n; while (n--) mpz_clear (B[n]); (*__gmp_free_func) (B, n0 * sizeof (mpz_t)); mpfr_clear (t); mpfr_clear (u); mpfr_clear (invxx); f = 0; while (e > 1) { f++; e = (e + 1) / 2; /* Invariant: 2^f * e does not decrease */ } return f; }