In relation to a recent post regarding how to declare the array shape concisely, I tried the following three patterns, i.e., (A) automatic re-allocation, (B) sourced allocation, and (C) allocation with assumed shape. Then gfortran seems to give incorrect results for b(:,:) in the case of sourced allocation. Here, am I doing something wrong, or is this simply because it is not yet fully supported by gfortran? Although the latter seems likely, I am not very sure if my installation or usage of gcc5 and 6 is correct (I am using Linux x86_64).
program main
implicit none
integer, parameter :: p=3, q=4, r=5
integer a( p, q, r ), i, j, k
integer, allocatable :: b( :, : )
a = reshape( [ ((( 100*i + 10*j + k, i=1,p), j=1,q), k=1,r) ], [p,q,r] )
print *
print *, "shape( a ) = ", shape( a )
print *, "a(:,:,:) = ", a
print *, "a(:,1,:) = ", a(:,1,:)
b = a( :, 1, : ) !! (A) automatic (re)allocation
! allocate( b, source = a( :, 1, : ) ) !! (B) sourced allocation
! allocate( b, mold = a( :, 1, : ) ) !! (C) allocation with assumed shape
print *
print *, "shape( b ) = ", shape( b )
print *, "b(:,:) = ", b
end
Results: (In all cases, automatic reallocation gives the correct result.)
gfortran4.8.2
[A]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B], [C]
f951: internal compiler error: Segmentation fault
gfortran5.2.1
[A]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B], [C]
allocate( b, source = a( :, 1, : ) )
1
Error: Array specification required in ALLOCATE statement at (1)
gfortran6.0.0 (experimental)
[A]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B] <--- seems incorrect
shape( b ) = 3 5
b(:,:) = 0 -1094645928 57 141 241 341 142 242 342 143 243 343 144 244 344
[C]
shape( b ) = 3 5
b(:,:) = (garbage data, reasonable)
Intel Fortran 14.0.1 (-assume realloc_lhs)
[A]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[C]
shape( b ) = 3 5
b(:,:) = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Oracle Fortran 12.4
[A]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[B]
shape( b ) = 3 5
b(:,:) = 111 211 311 112 212 312 113 213 313 114 214 314 115 215 315
[C]
shape( b ) = 3 5
b(:,:) = (garbage data, reasonable)
Sourced allocation was introduced in Fortran 2003 and the rules/constraints were changed in Fortran 2008. Rejection of the program by gfortran 5.2.1 would appear to be a consequence of following F2003.
Under F2003 sourced allocation required the explicit specification of array bounds for the array to be allocated. Under F2008 this is not required, and additionally multiple objects to be allocated could be specified. So, your code isn't valid F2003.
The program (well, that allocation part) is, though, valid F2008: the bounds of the array to be allocated may come from the source expression just as the value does. The contiguity or otherwise of the array section shouldn't be important as it's the value (and bounds) of the expression being key. Naturally, the calculation of bounds of the expression array offers opportunity for things to go wrong.
In conclusion, the allocation statement is valid under F2008 but not under F2003. A compiler which is using the F2003 rules must be able to detect the violation rather than being free to give nonsense. But F2008 is easy enough to do buggily.
And, thanks to your testing, the safe way to write this code for gfortran would be
allocate(b(p,r), source=a(:,1,:))
Indeed, documentation for gfortran lists the giving of bounds as being "unimplemented".
Related
I'm new to C++ and I wanted to compress a vector via ZSTD compression library. I used ZSTD simple API ZSTD_compress and ZSTD_decompress in the same way as the example. But I found a wired issue that when I compressed and decompressed a vector, the decompressed vector was not the same as the original vector. I'm not sure which part of my operation went wrong.
I looked at ZSTD's GitHub homepage and didn't find an answer. Please help or try to give some ideas how to solve it.
Example C code: https://github.com/facebook/zstd/blob/dev/examples/simple_compression.c
//Initialize a vector
vector<int> NumToCompress ;
NumToCompress.resize(10000);
for(int i = 0; i < 10000; i++)
{
NumToCompress[i] = rand()% 255;
}
//compress
int* com_ptr = NULL;
size_t NumSize = NumToCompress.size();
size_t Boundsize = ZSTD_compressBound(NumSize);
com_ptr =(int*) malloc(Boundsize);
size_t ComSize;
ComSize = ZSTD_compress(com_ptr,Boundsize,NumToCompress.data(),NumToCompress.size(),ZSTD_fast);
//decompress
int* decom_ptr = NULL;
unsigned long long decom_Boundsize;
decom_Boundsize = ZSTD_getFrameContentSize(com_ptr, ComSize);
decom_ptr = (int*)malloc(decom_Boundsize);
size_t DecomSize;
DecomSize = ZSTD_decompress(decom_ptr, decom_Boundsize, com_ptr, ComSize);
vector<int> NumAfterDecompress(decom_ptr,decom_ptr+DecomSize);
//check if two vectors are same
if(NumToCompress == NumAfterDecompress)
{
cout << "Two vectors are same" << endl;
}else
{cout << "Two vectors are insame" << endl;}
free(com_ptr);
free(decom_ptr);
case 1: If zstd can compress std::vector directly?
case 2: How to properly compress vectors with zstd if zstd can compress std::vector directly ?
Two vectors are insame
Original vector:
163 151 162 85 83 190 241 252 249 121 107 82 20 19 233 226 45 81 142 31 86 8 87 39 167 5 212 208 82 130 119 117 27 153 74 237 88 61 106 82 54 213 36 74 104 142 173 149 95 60 53 181 196 140 221 108 17 50 61 226 180 180 89 207 206 35 61 39 223 167 249 150 252 30 224 102 44 14 123 140 202 48 66 143 188 159 123 206 209 184 177 135 236 138 214 187 46 21 99 14
Decompressed vector:
163 151 162 85 83 190 241 252 249 121 107 82 20 19 233 226 45 81 142 31 86 8 87 39 167 0 417 0551929248 21916 551935408 21916 551933352 21916 551939512 21916 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Seems likely that your API expects the size to be in bytes but you give the size as the number of elements. So you need to multiply the number of elements by the size of each element. Like this
ComSize = ZSTD_compress(com_ptr, Boundsize, NumToCompress.data(),
NumToCompress.size()*sizeof(int), ZSTD_fast);
and similarly when you decompress you need to divide by the element size
DecomSize = ZSTD_decompress(decom_ptr, decom_Boundsize, com_ptr, ComSize);
vector<int> NumAfterDecompress(decom_ptr, decom_ptr+DecomSize/sizeof(int));
I have to read a data set of 50 numbers from a text file. It's all in a row with a space delimiter and in multiple uneven lines. for example:
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15
16 17 18 19 20 21
Etc.
The first 25 numbers belong to group 1, and the 2nd 25 belong to group 2. So I need to make a group variable (binary either 1 or 2), a count number (1 to 25), and a value variable which is holding the value of the number.
I am stuck on how to split the data in half when reading it. I tried to use truncover but it did not work.
Try something like this, replacing the datalines keyword with the path to your file:
data groups;
infile datalines;
format number 8. counter 2. group 1.; * Not mandatory, used here to order variables;
retain group (1);
input number ##;
counter + 1;
if counter = 26 then do;
group = 2;
counter = 1;
end;
datalines;
192 105 435 448 160 499 184 246 388 190 316
139 146 147 192 231 449 101 216 342 399 352 122 418
280 400 187 352 321 180 425 500 320 179 105
232 105 323 132 106 255 449
186 135 472 174 119 255
308 350
run;
a = 100
for b in range(10,a):
c = b%10
if c == 0:
c += 3
c = c*b
print c
I was trying to make a random generator without using random function and I made this, does it generate random numbers?
Short Answer:
No.
Your code will print
30 11 24 39 56 75 96 119 144 171 60 21 44 69 96 125 156 189 224 261 90 31 64 99 136 175 216 259 304 351 120 41 84 129 176 225 276 329 384 441 150 51 104 159 216 275 336 399 464 531 180 61 124 189 256 325 396 469 544 621 210 71 144 219 296 375 456 539 624 711 240 81 164 249 336 425 516 609 704 801 270 91 184 279 376 475 576 679 784 891
every time.
Computers and programs like these are deterministic. If you sat down with a pen and paper you could tell me exactly which of these number would occur, when they would occur.
Random number generation is difficult, what I would recommend is using time to (seem to) randomize the output.
import time
print int(time.time() % 10)
This will give you a "random" number between 0 and 9.
time.time() gives you the number of milliseconds since (I believe) epoch time. It's a floating point number so we have to cast to an int if we want a "whole" integer number.
Caveat: This solution is not truly random, but will act in a much more "random" fashion.
I want to get a set of random even numbers between 50 and 100, and this is what I wrote:
int x;
x=(2*(50+rand()%(100-50+1)));
when I output this, I get
186
166
112
190
150
160
146
104
194
168
194
178
102
200
192
130
168
134
146
184
136
which are not in between 50 and 100...why?
thanks for helping me!
Your computation is wrong, you ask for 2 times a number between 50 and 100.
Go with
x = 2 * ( rand() % 25 ) + 50
int x;
x=50+(2*(rand()%(26)));
X = rand()%(upper-lower+1) + lower
In your case : x = rand()%51 + 50
I encountered what seemed to me as strange behavior using glUniformMatrix4x3fv. Specifically when I give TRUE as for the transpose flag entire rows of my matrices are missing in my shader variable (and those that are there are therefor out of order).
For example. Say I have in my GLSL shader:
mat4x3 T[m];
Then in my C++ OpenGL call I want to send a matrix whose entries are (stored in row-major order):
T =
1 2 3
4 5 6
7 8 9
10 11 12
101 102 103
104 105 106
107 108 109
110 111 112
101 102 103
204 205 206
207 208 209
210 211 212
...
And I call
glUniformMatrix4x3fv(location,m,false,T);
Then I see in my shader that the each matrix comes out correctly as:
T[0] ->
1 4 7 10
2 5 8 11
3 6 9 12
T[1] ->
101 104 107 110
102 105 108 111
103 106 109 112
...
BUT, if I store my matrix on the C++ side as (again row-major order):
T =
1 4 7 10
2 5 8 11
3 6 9 12
101 104 107 110
102 105 108 111
103 106 109 112
201 204 207 210
202 205 208 211
203 206 209 212
...
And try to use the transpose flag as TRUE with:
glUniformMatrix4x3fv(location,m,true,T);
Then in my shader the matrices show up incorrectly as:
T[0] ->
1 4 7 10
2 5 8 11
3 6 9 12
T[1] ->
102 105 108 111
103 106 109 112
201 204 207 210
T[2] ->
203 206 209 212
301 304 307 310
302 305 308 311
...
Every 4th row of my data is missing.
Is there a sensible reason for this? I find nothing in the spec (s2.1 p82).
GL_VERSION: 2.1 NVIDIA-1.6.36
GL_SHADING_LANGUAGE_VERSION: 1.20
Then in my C++ OpenGL call I want to send a matrix whose entries are (stored in row-major order):
That's not row-major order. That's column-major order.
Given the following 4x3 matrix:
1 4 7 10
2 5 8 11
3 6 9 12
This is what a C++ array of this data in column-major order would look like:
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
That's what your data is. Feel free to insert space wherever you want; it's entirely irrelevant.
This is what the same data in row-major order looks like:
{1, 4, 7, 10, 2, 5, 8, 11, 3, 6, 9, 12}
As to the specific issue you encountered with transposing your data for 4x3 matrices, it may simply be a driver bug.