Issue when trying to generate large dataset - c

I want to create large dataset of 60M elements each of dim = 256 (later will be written to a file). I wrote the following to do so:
#define N 60000000L
#define DIM 256
int main(){
int i,j;
double tmp, *data;
data = calloc(N*DIM, sizeof(double));
tmp = 1.0 / RAND_MAX;
for (i = 0; i < N*DIM; i++) data[i] = (double) rand() * tmp - 0.5;
// TODO: Save data buffer in file
free(data);
}
But I get this error:
main.c:111:19: warning: comparison of constant 7695802368 with expression of type 'int' is always
true [-Wtautological-constant-out-of-range-compare]
for (i = 0; i < N*DIM; i++) data[i] = (double) rand() * tmp - 0.5;
~ ^ ~~~~~~~~~~
1 warning generated.
Can someone hint me please why this issue exists and how to get rid of it? Thank you

The int type on your machine cannot hold a large enough number to ever be >= 7695802368. This means your int type is 32 bits. You'll need to use a 64 bit number, long long int or probably more appropriately, unsigned long long int.

Use size_t math with memory allocations and indexing.
It is the Goldilocks type for indexing/sizing, neither too narrow, nor too wide. Keep in mind that it is some unsigned type.
//#define N 60000000L
#define N ((size_t) 60000000u)
#define DIM 256
int main(){
size_t i;// use the best type for indexing
double tmp, *data;
size_t n = N*DIM;
data = calloc(n, sizeof *data); // de-ref the pointer,
if (data) { // check allocation
tmp = 1.0 / RAND_MAX;
for (i = 0; i < n; i++) {
data[i] = (double) rand() * tmp - 0.5;

The warning explains it for you: you're testing a signed integer (that probably maxes out at 2,147,483,647, and is clearly less than the value you're testing against, considering your compiler warning) to see if its value is less than a value that's over 7 billion: it will always be true. Did you maybe mean to do i < N?

Related

Store a large number as separate digits in an array [duplicate]

I am trying to calculate 100! (that is, the factorial of 100).
I am looking for the simplest way to accomplish this using C. I have read around but have not found a concrete answer.
If you must know, I program in Xcode in Mac os X.
If you're looking for a simple library, libtommath (from libtomcrypt) is probably what you want.
If you're looking to write a simple implementation yourself (either as a learning exercise or because you only need a very limited subset of bigint functionality and don't want to tack on a dependency to a large library, namespace pollution, etc.), then I might suggest the following for your problem:
Since you can bound the size of the result based on n, simply pre-allocate an array of uint32_t of the required size to hold the result. I'm guessing you'll want to print the result, so it makes sense to use a base that's a power of 10 (i.e. base 1000000000) rather than a power of 2. That is to say, each element of your array is allowed to hold a value between 0 and 999999999.
To multiply this number by a (normal, non-big) integer n, do something like:
uint32_t carry=0;
for(i=0; i<len; i++) {
uint64_t tmp = n*(uint64_t)big[i] + carry;
big[i] = tmp % 1000000000;
carry = tmp / 1000000000;
}
if (carry) big[len++] = carry;
If you know n will never be bigger than 100 (or some other small number) and want to avoid going into the 64-bit range (or if you're on a 64-bit platform and want to use uint64_t for your bigint array), then make the base a smaller power of 10 so that the multiplication result will always fit in the type.
Now, printing the result is just something like:
printf("%lu", (long)big[len-1]);
for(i=len-1; i; i--) printf("%.9lu", (long)big[i-1]);
putchar('\n');
If you want to use a power of 2 as the base, rather than a power of 10, the multiplication becomes much faster:
uint32_t carry=0;
for(i=0; i<len; i++) {
uint64_t tmp = n*(uint64_t)big[i] + carry;
big[i] = tmp;
carry = tmp >> 32;
}
if (carry) big[len++] = carry;
However, printing your result in decimal will not be so pleasant... :-) Of course if you want the result in hex, then it's easy:
printf("%lx", (long)big[len-1]);
for(i=len-1; i; i--) printf("%.8lx", (long)big[i-1]);
putchar('\n');
Hope this helps! I'll leave implementing other things (like addition, multiplication of 2 bigints, etc) as an exercise for you. Just think back to how you learned to do base-10 addition, multiplication, division, etc. in grade school and teach the computer how to do that (but in base-10^9 or base-2^32 instead) and you should have no problem.
If you're willing to use a library implementation the standard one seems to be GMP
mpz_t out;
mpz_init(out);
mpz_fac_ui(out,100);
mpz_out_str(stdout,10,out);
should calculate 100! from looking at the docs.
You asked for the simplest way to do this. So, here you go:
#include <gmp.h>
#include <stdio.h>
int main(int argc, char** argv) {
mpz_t mynum;
mpz_init(mynum);
mpz_add_ui(mynum, 100);
int i;
for (i = 99; i > 1; i--) {
mpz_mul_si(mynum, mynum, (long)i);
}
mpz_out_str(stdout, 10, mynum);
return 0;
}
I tested this code and it gives the correct answer.
You can also use OpenSSL bn; it is already installed in Mac OS X.
You can print factorial 1000 in C with just 30 lines of code, <stdio.h> and char type :
#include <stdio.h>
#define B_SIZE 3000 // number of buffered digits
struct buffer {
size_t index;
char data[B_SIZE];
};
void init_buffer(struct buffer *buffer, int n) {
for (buffer->index = B_SIZE; n; buffer->data[--buffer->index] = (char) (n % 10), n /= 10);
}
void print_buffer(const struct buffer *buffer) {
for (size_t i = buffer->index; i < B_SIZE; ++i) putchar('0' + buffer->data[i]);
}
void natural_mul_buffer(struct buffer *buffer, const int n) {
int a, b = 0;
for (size_t i = (B_SIZE - 1); i >= buffer->index; --i) {
a = n * buffer->data[i] + b;
buffer->data[i] = (char) (a % 10);
b = a / 10;
}
for (; b; buffer->data[--buffer->index] = (char) (b % 10), b /= 10);
}
int main() {
struct buffer number_1 = {0};
init_buffer(&number_1, 1);
for (int i = 2; i <= 100; ++i)
natural_mul_buffer(&number_1, i);
print_buffer(&number_1);
}
You will find faster but the “little” factorial(10000) is here computed ≈ instantly.
You can put it into a fact.c file then compile + execute :
gcc -O3 -std=c99 -Wall -pedantic fact.c ; ./a.out ;
If you want to execute some base conversion there is a solution, see also Fibonacci(10000), Thank You.

Unsigned Long Int overflow when calculating pow

I am trying to make a function that quickly calculates x^y mod z. It works well when calculating something like 2^63 mod 3, but at 2^64 mod 3 and higher exponents it just returns 0.
I am suspecting an overflow somewhere, but I can't pin it down. I have tried explicit casts at the places where calculations (* and mod) are made, I have also made my storage variables (resPow, curPow) unsigned long long int (as Suggested here) but that didn't help much.
typedef unsigned long int lint;
lint fastpow(lint nBase, lint nExp, lint nMod) {
int lastTrueBit = 0;
unsigned long long int resPow = 1ULL;
unsigned long long int curPow = nBase;
for (int i = 0; i < 32; i++) {
int currentBit = getBit(nExp, i);
if (currentBit == 1) {
for (lint j = 0; j < i - lastTrueBit; j++) {
curPow = curPow * curPow;
}
resPow =resPow * curPow;
lastTrueBit = i;
}
}
return resPow % nMod;
}
I am suspecting an overflow somewhere,
Yes, both curPow * curPow and resPow * curPow may mathematically overflow.
The usual way to contain overflow here is to perform mod on intermediate products.
// curPow = curPow * curPow;
curPow = (curPow * curPow) % nMod;
// resPow =resPow * curPow;
resPow = (resPow * curPow) % nMod;
This is sufficient when nMod < ULLONG_MAX/(nMod - 1). (The mod value is half the precision of unsigned long long). Otherwise more extreme measures are needed as in: Modular exponentiation without range restriction.
Minor stuff
for(int i = 0; i < 32; i++) assumes lint/unsigned long is 32 bits. Portable code would avoid that magic number. unsigned long is 64-bits on various platforms.
LL is not needed here. U remains useful to quiet various compiler warnings.
// unsigned long long int resPow = 1ULL;
unsigned long long int resPow = 1U;

Malloc() to create a new size for integers for use with math - Guidance needed

My goal is to create a integer type with a bigger size than 4 bytes, or 8 if I use long. I tried malloc to try and give more bytes in the memory for a bigger integer, but it still broke on the 31st iteration (gave a negative number). here's my code:
int main()
{
int x = 31; //(normally an int can do up to 30 without going negative so this is my test number)
int i;
int *bigNum = NULL;
bigNum = malloc((sizeof(int)*2));
*bigNum = 1;
for (i=0; i<x; i++) {
*bigNum = *bigNum * 2;
printf("%d \n", *bigNum);
}
free(bigNum);
}
Output:
2
4
...
..
...
1073741824
-2147483648
Although you have allocated more memory for your integer, no other part of the system knows this, including:
the compiler doesn't know this;
the CPU chip doesn't know this.
printf doesn't know this.
So all calculations are just carried out using the native int size.
Note that you can't tell the CPU chip you use larger integers; it is a physical/design limitation of the chip.
Dereferencing an int * gives you an int no matter how much extra memory you allocate for it.
If you want a dat type able to hold more information, try a long (although the guarantee is that it will be at least as big as an int).
If you want to handle integers beyond what your implementation provides, use a bignum library, like MPIR.
goal is to create a integer type with a bigger size
To handle multi-int integers, code also needs supporting functions for each basic operation:
int main(void) {
int x = 31;
RandBigNum *bigNum = RandBigNum_Init();
RandBigNum_Assign_int(bigNum, 1);
for (int i=0; i<x; i++) {
RandBigNum_Muliply_int(bigNum, 2);
RandBigNum_Print(bigNum);
printf(" \n");
}
Now, how might implement all this? Many approaches.
Below is a simply, incomplete and untested one. It is not necessarily a good approach, but to present an initial idea of the details needed to accomplish a big number library.
// Numbers are all positive. The first array element is the size of the number
typedef unsigned RandBigNum;
#define RandBigNum_MAXP1 (UINT_MAX + 1ull)
RandBigNum *RandBigNum_Init(void) {
return calloc(1, sizeof *RandBigNum);
}
void RandBigNum_Muliply_int(RandBigNum *x, unsigned scale) {
unsigned carry = 0;
for (unsigned i = 1; i <= x[0]; i++) {
unsigned long long product = 1ull * x[i] * scale + carry;
x[i] = product % RandBigNum_MAXP1;
carry *= product / RandBigNum_MAXP1;
}
if (carry) {
unsigned n = x[0] + 2;
x = realloc(x, sizeof *x * n); // re-alloc check omitted
x[x[0]] = carry;
x[0]++;
}
}
// many other functions

Comparing unsigned and signed int

I guess this is one of the classical questions.
As far as I know comparing unsigned and signed int are performed using unsigned arithmetic, which means that if length = -1 = unsigned max of 32 bits.
The code can be fixed by either declaring length to be an int, or by changing the test of the for loop to be i < length.
Declaring length to be an int, it's easy to understand, but changing the loop to be i < length not really easy.
If we have the following situation: 5 < -1 which if performed using unsigned arithmetic, in my computer yields 5 < 4294967295, how can this be a solution, it seems like it will access undefined elements.
Code
float sum_elements(float a[], unsigned length)
{
int i;
float result = 0;
for (i = 0; i <= length-1; i++)
result += a[i];
return result;
}
Consider the condition.
i <= length-1
As you mentioned, if length is zero then you will enter into a situation like 5 < 4294967295.
Changing the condition to "i < length" will prevent this.
Also changing type of variable "i" to "unsigned" makes sense because (a) it is array index. (b) you are comparing it with an "unsigned".
So I would prefer this code.
float sum_elements(float a[], unsigned length)
{
unsigned i = 0;
//float result = 0.0; //Refer comment section.
double result = 0.0;
for (i = 0; i < length; i++)
result += (double)a[i];
return result;
}
Option #1:
for (i = 0; i <= (int)length-1; i++)
Option #2:
for (i = 0; i+1 <= length; i++)
Option #3:
for (i = 0; i < length; i++)
It's your compilator job's, when he creates he's parser lexer, he uses a table for your variables. If he saw something like :
float a = b + 60
60 will be cast in 60.0 by your compilator.
I think this is the same thing here:
(unsigned int)length = (unsigned int)length (int)-1
becomes:
(unsigned int)length = (int)length (int)-1;
If you want a proper arithmetic comparison, you should use the flag -Wextra
A pedantic <= compare of and int <= unsigned would test for negative-ness first.
for (i = 0; i < 0 || ((unsigned) i) <= length-1; i++)
Removing the -1 helps to avoid overflow.
for (i = 0; i < 0 || ((unsigned) i) < length; i++)
A good compiler will likely optimize the code so 2 compares are not actually in the executable.
If -Wsign-conversion or its equivalent compiler option is not used, drop the cast for cleaner code #R..
for (i = 0; i < 0 || i < length; i++)
As well commented by #chqrlie the compare may perform well but subsequent operations on i may be a problem. In particular when i == INT_MAX, the i++ is UB.
Better to use size_t (an unsigned type) for array size computation and indexing.
float sum_elements(float a[], size_t length) {
float result = 0;
size_t i;
for (i = 0; i < length; i++)
result += a[i];
return result;
}
Your code will not perform as expected in 2 cases:
if length == 0, length - 1, computed using unsigned arithmetic, is a very large number and comparing i <= length - 1 will be always true because the comparison is also performed using unsigned arithmetics.
if length is larger than the maximum integer value, i can never reach such a value and although the comparison performed using unsigned arithmetic will work as expected, the indexing a[i] will be incorrect on 64-bit systems where the negative index will point outside the array.
The compiler correctly diagnoses a real problem. Using a signed type for i and comparing that to an unsigned length expression can lead to unexpected behavior. Correct the problem this way:
float sum_elements(float a[], unsigned length) {
double result = 0.0;
for (unsigned i = 0; i < length; i++) {
result += a[i];
}
return result;
}
Notes:
the types for length and i really should be size_t as this may be a larger type than unsigned.
the sum should be computed using double arithmetics, to achieve better precision than using float. Precision will be better, but still limited. Summing the array elements in a different order can produce a different result.
Lose the i variable, to save a little stack space and make the function faster.
float sum_elements(float a[], unsigned length)
{
float result = 0;
while (length--)
result += *a++;
return result;
}

Numerical Integral from 0 to infinity

My aim is to calculate the numerical integral of a probability distribution function (PDF) of the distance of an electron from the nucleus of the hydrogen atom in C programming language. I have written a sample code however it fails to find the numerical value correctly due to the fact that I cannot increase the limit as much as its necessary in my opinion. I have also included the library but I cannot use the values stated in the following post as integral boundaries: min and max value of data type in C . What is the remedy in this case? Should switch to another programming language maybe? Any help and suggestion is appreciated, thanks in advance.
Edit: After some value I get the error segmentation fault. I have checked the actual result of the integral to be 0.0372193 with Wolframalpha. In addition to this if I increment k in smaller amounts I get zero as a result that is why I defined r[k]=k, I know it should be smaller for increased precision.
#include <stdio.h>
#include <math.h>
#include <limits.h>
#define a0 0.53
int N = 200000;
// This value of N is the highest possible number in long double
// data format. Change its value to adjust the precision of integration
// and computation time.
// The discrete integral may be defined as follows:
long double trapezoid(long double x[], long double f[]) {
int i;
long double dx = x[1]-x[0];
long double sum = 0.5*(f[0]+f[N]);
for (i = 1; i < N; i++)
sum+=f[i];
return sum*dx;
}
main() {
long double P[N], r[N], a;
// Declare and initialize the loop variable
int k = 0;
for (k = 0; k < N; k++)
{
r[k] = k ;
P[k] = r[k] * r[k] * exp( -2*r[k] / a0);
//printf("%.20Lf \n", r[k]);
//printf("%.20Lf \n", P[k]);
}
a = trapezoid(r, P);
printf("%.20Lf \n", a);
}
Last Code:
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#define a0 0.53
#define N LLONG_MAX
// This value of N is the highest possible number in long double
// data format. Change its value to adjust the precision of integration
// and computation time.
// The discrete integral may be defined as follows:
long double trapezoid(long double x[],long double f[]) {
int i;
long double dx = x[1]-x[0];
long double sum = 0.5*(f[0]+f[N]);
for (i = 1; i < N; i++)
sum+=f[i];
return sum*dx;
}
main() {
printf("%Ld", LLONG_MAX);
long double * P = malloc(N * sizeof(long double));
long double * r = malloc(N * sizeof(long double));
// Declare and initialize the loop variable
int k = 0;
long double integral;
for (k = 1; k < N; k++)
{
P[k] = r[k] * r[k] * expl( -2*r[k] / a0);
}
integral = trapezoid(r, P);
printf("%Lf", integral);
}
Edit last code working:
#include <stdio.h>
#include <math.h>
#include <limits.h>
#include <stdlib.h>
#define a0 0.53
#define N LONG_MAX/100
// This value of N is the highest possible number in long double
// data format. Change its value to adjust the precision of integration
// and computation time.
// The discrete integral may be defined as follows:
long double trapezoid(long double x[],long double f[]) {
int i;
long double dx = x[1]-x[0];
long double sum = 0.5*(f[0]+f[N]);
for (i = 1; i < N; i++)
sum+=f[i];
return sum*dx;
}
main() {
printf("%Ld \n", LLONG_MAX);
long double * P = malloc(N * sizeof(long double));
long double * r = malloc(N * sizeof(long double));
// Declare and initialize the loop variable
int k = 0;
long double integral;
for (k = 1; k < N; k++)
{
r[k] = k / 100000.0;
P[k] = r[k] * r[k] * expl( -2*r[k] / a0);
}
integral = trapezoid(r, P);
printf("%.15Lf \n", integral);
free((void *)P);
free((void *)r);
}
In particular I have changed the definition for r[k] by using a floating point number in the division operation to get a long double as a result and also as I have stated in my last comment I cannot go for Ns larger than LONG_MAX/100 and I think I should investigate the code and malloc further to get the issue. I have found the exact value that is obtained analytically by taking the limits; I have confirmed the result with TI-89 Titanium and Wolframalpha (both numerically and analytically) apart from doing it myself. The trapezoid rule worked out pretty well when the interval size has been decreased. Many thanks for all the posters here for their ideas. Having a value of 2147483647 LONG_MAX is not that particularly large as I expected by the way, should the limit not be around ten to power 308?
Numerical point of view
The usual trapezoid method doesn't work with improper integrals. As such, Gaussian quadrature rules are much better, since they not only provide 2n-1 exactness (that is, for a polynomial of degree 2n-1 they will return the correct solution), but also manage improper integrals by using the right weight function.
If your integral is improper in both sides, you should try the Gauss-Hermite quadrature, otherwise use the Gauss-Laguerre quadrature.
The "overflow" error
long double P[N], r[N], a;
P has a size of roughly 3MB, and so does r. That's too much memory. Allocate the memory instead:
long double * P = malloc(N * sizeof(long double));
long double * r = malloc(N * sizeof(long double));
Don't forget to include <stdlib.h> and use free on both P and r if you don't need them any longer. Also, you may not access the N-th entry, so f[N] is wrong.
Using Gauss-Laguerre quadrature
Now Gauss-Laguerre uses exp(-x) as weight function. If you're not familiar with Gaussian quadrature: the result of E(f) is the integral of w * f, where w is the weight function.
Your f looks like this, and:
f x = x^2 * exp (-2 * x / a)
Wait a minute. f already contains exp(-term), so we can substitute x with t = x * a /2 and get
f' x = (t * a/2)^2 * exp(-t) * a/2
Since exp(-t) is already part of our weight function, your function fits now perfectly into the Gauss-Laguerre quadrature. The resulting code is
#include <stdio.h>
#include <math.h>
/* x[] and a[] taken from
* https://de.wikipedia.org/wiki/Gau%C3%9F-Quadratur#Gau.C3.9F-Laguerre-Integration
* Calculating them by hand is a little bit cumbersome
*/
const int gauss_rule_length = 3;
const double gauss_x[] = {0.415774556783, 2.29428036028, 6.28994508294};
const double gauss_a[] = {0.711093009929, 0.278517733569, 0.0103892565016};
double f(double x){
return x *.53/2 * x *.53/2 * .53/2;
}
int main(){
int i;
double sum = 0;
for(i = 0; i < gauss_rule_length; ++i){
sum += gauss_a[i] * f(gauss_x[i]);
}
printf("%.10lf\n",sum); /* 0.0372192500 */
return 0;
}

Resources