all
I have two input files like this :
file1 :
#W #S #this line dosen't exit
110 170 Bias
110 200 Bias
110 215 Bias
110 320 Bias
125 170 Bias
125 200 Bias
125 215 Bias
125 320 Bias
135 170 Bias
135 200 Bias
135 215 Bias
135 320 Bias
140 170 Bias
140 200 Bias
140 215 Bias
140 320 Bias
file2 :
FUNCTION BIAS ( W, S )
Bias = 0
IF AND ( W >= 0, W < 120 ) THEN
IF ( S >= 0 ) THEN Bias = -1
IF ( S >= 180 ) THEN Bias = -2
IF ( S >= 190 ) THEN Bias = -3
IF ( S >= 200 ) THEN Bias = -4
IF ( S >= 210 ) THEN Bias = -5
IF ( S >= 220 ) THEN Bias = -6
IF ( S >= 240 ) THEN Bias = -7
ENDIF
IF AND ( W >= 120, W < 130 ) THEN
IF ( S >= 0 ) THEN Bias = -11
IF ( S >= 180 ) THEN Bias = -12
IF ( S >= 190 ) THEN Bias = -13
IF ( S >= 200 ) THEN Bias = -14
IF ( S >= 210 ) THEN Bias = -15
IF ( S >= 220 ) THEN Bias = -16
IF ( S >= 240 ) THEN Bias = -17
ENDIF
IF AND ( W >= 130, W < 140 ) THEN
IF ( S >= 0 ) THEN Bias = 1
IF ( S >= 180 ) THEN Bias = 2
IF ( S >= 190 ) THEN Bias = 3
IF ( S >= 200 ) THEN Bias = 4
IF ( S >= 210 ) THEN Bias = 5
IF ( S >= 220 ) THEN Bias = 6
IF ( S >= 240 ) THEN Bias = 7
ENDIF
IF ( W >= 140 ) THEN
IF ( S >= 0 ) THEN Bias = 11
IF ( S >= 180 ) THEN Bias = 12
IF ( S >= 190 ) THEN Bias = 13
IF ( S >= 200 ) THEN Bias = 14
IF ( S >= 210 ) THEN Bias = 15
IF ( S >= 220 ) THEN Bias = 16
IF ( S >= 240 ) THEN Bias = 17
ENDIF
RETURN (Bias)
What I wanna do is to find out the corresponding value of a math function : "BIAS(W,S)" with the input (W,S) pair from file1
for example : W/S=135/195, "W" satisfy
IF AND ( W >= 130, W < 140 )
so we will go to check "S"
IF ( S >= 0 ) THEN Bias = 1
IF ( S >= 180 ) THEN Bias = 2
IF ( S >= 190 ) THEN Bias = 3
IF ( S >= 200 ) THEN Bias = 4
IF ( S >= 210 ) THEN Bias = 5
IF ( S >= 220 ) THEN Bias = 6
IF ( S >= 240 ) THEN Bias = 7
then finally we can find out S=195 is in between 190 and 200, the value of BIAS(W,S) is 3
what I want for the output is like this :
110 170 Bias -1
110 200 Bias -4
110 215 Bias -5
110 320 Bias -7
125 170 Bias -11
125 200 Bias -14
125 215 Bias -15
125 320 Bias -17
135 170 Bias 1
135 200 Bias 4
135 215 Bias 5
135 320 Bias 7
140 170 Bias 11
140 200 Bias 14
140 215 Bias 15
140 320 Bias 17
It's very easy to check by human eyes
but as you can see, file2 is basically a text file instead of a regular 2D-array numerical file, How can I extract the corresponding value? Any hint?
I just translated your logic into awk:
script.awk:
{
w=$1;
s=$2;
if (w >= 0 && w < 120) {
if ( s >= 0) { bias= -1 }
if ( s >= 180 ) { bias= -2 }
if ( s >= 190 ) { bias= -3 }
if ( s >= 200 ) { bias= -4 }
if ( s >= 210 ) { bias= -5 }
if ( s >= 220 ) { bias= -6 }
if ( s >= 240 ) { bias= -7 }
}
if (w >= 120 && w < 130) {
if ( s >= 0) { bias= -11 }
if ( s >= 180 ) { bias= -12 }
if ( s >= 190 ) { bias= -13 }
if ( s >= 200 ) { bias= -14 }
if ( s >= 210 ) { bias= -15 }
if ( s >= 220 ) { bias= -16 }
if ( s >= 240 ) { bias= -17 }
}
if (w >= 130 && w < 140) {
if ( s >= 0) { bias= 1 }
if ( s >= 180 ) { bias= 2 }
if ( s >= 190 ) { bias= 3 }
if ( s >= 200 ) { bias= 4 }
if ( s >= 210 ) { bias= 5 }
if ( s >= 220 ) { bias= 6 }
if ( s >= 240 ) { bias= 7 }
}
if (w >= 140 ) {
if ( s >= 0) { bias= 11 }
if ( s >= 180 ) { bias= 12 }
if ( s >= 190 ) { bias= 13 }
if ( s >= 200 ) { bias= 14 }
if ( s >= 210 ) { bias= 15 }
if ( s >= 220 ) { bias= 16 }
if ( s >= 240 ) { bias= 17 }
}
print $0" "bias;
}
Execution:
awk -f script.awk file1
110 170 Bias -1
110 200 Bias -4
110 215 Bias -5
110 320 Bias -7
125 170 Bias -11
125 200 Bias -14
125 215 Bias -15
125 320 Bias -17
135 170 Bias 1
135 200 Bias 4
135 215 Bias 5
135 320 Bias 7
140 170 Bias 11
140 200 Bias 14
140 215 Bias 15
140 320 Bias 17
Run the tst.awk script below on "file2" to convert the script in whatever language that is to awk and save it's output to a new file named "getbias.awk", then run:
awk -f getbias.awk '<your script>' file1
where <your script> parses file1 and calls the generated getbias() function below to get the bias values for each line.
$ cat tst.awk
{
sub(/BIAS/,"getbias")
sub(/ENDIF/,"}")
sub(/ THEN/,"")
$0 = tolower($0)
}
/^function/ { sub(/\)/,",\tbias )"); $0 = $0 " {" }
/^return/ { $0 = $0 ORS "}" }
/^if/ { sub(/ and/,""); sub(/,/," \\&\\&"); $0 = $0 " {" }
{ print }
.
$ awk -f tst.awk file2
function getbias ( w, s , bias ) {
bias = 0
if ( w >= 0 && w < 120 ) {
if ( s >= 0 ) bias = -1
if ( s >= 180 ) bias = -2
if ( s >= 190 ) bias = -3
if ( s >= 200 ) bias = -4
if ( s >= 210 ) bias = -5
if ( s >= 220 ) bias = -6
if ( s >= 240 ) bias = -7
}
if ( w >= 120 && w < 130 ) {
if ( s >= 0 ) bias = -11
if ( s >= 180 ) bias = -12
if ( s >= 190 ) bias = -13
if ( s >= 200 ) bias = -14
if ( s >= 210 ) bias = -15
if ( s >= 220 ) bias = -16
if ( s >= 240 ) bias = -17
}
if ( w >= 130 && w < 140 ) {
if ( s >= 0 ) bias = 1
if ( s >= 180 ) bias = 2
if ( s >= 190 ) bias = 3
if ( s >= 200 ) bias = 4
if ( s >= 210 ) bias = 5
if ( s >= 220 ) bias = 6
if ( s >= 240 ) bias = 7
}
if ( w >= 140 ) {
if ( s >= 0 ) bias = 11
if ( s >= 180 ) bias = 12
if ( s >= 190 ) bias = 13
if ( s >= 200 ) bias = 14
if ( s >= 210 ) bias = 15
if ( s >= 220 ) bias = 16
if ( s >= 240 ) bias = 17
}
return (bias)
}
Related
I am trying to specify each dimension range (length, width and height) of values specify criteria based on the length, width and height.
In data table I have 3 columns are length, width,height based on the 3 columns I would like to generate status columns which is based on the below mentioned condition range.
Conditions Range
Length, width and height is start from 1 to 300 then A1.
Length, width and height is start from 301 to 650 then A2.
Length, width and height is start from 651 to 900 then A3.
Length, width and height is start from 901 to 1200 then A4
Length, width and height is start from 1201 above then XXX
Data
LENGTH
WIDTH
HEIGHT
DESIRED RESULT RANGE
NA
NA
NA
NA
20000
5000
230
XX
400
300
140
A1
BLANKS
600
400
285
A2
600
400
285
A2
400
300
150
A1
280
230
170
A1
320
320
320
A1
320
320
320
A1
600
400
140
A1
400
300
140
A1
400
300
140
A1
370
320
340
A1
320
240
250
A1
300
200
90
A1
400
290
140
A1
600
400
285
A1
Table and result look like
Any suggestions please
Well, you may try the following dax measure, as it will assign all row to each category, and assign to Other if does not match any of the criteria, do take note due to your data contain NA, therefore all the value is in Text for that need to convert to number during calculation:
Result = IF(Sheet1[LENGTH] = "NA" || Sheet1[WIDTH] = "NA" || Sheet1[HEIGHT] ="NA", "NA",
IF(VALUE(Sheet1[LENGTH])>0 && VALUE(Sheet1[LENGTH]) <=300 && VALUE(Sheet1[WIDTH]) >0 && VALUE(Sheet1[WIDTH]) <=300 && VALUE(Sheet1[HEIGHT]) >0 && VALUE(Sheet1 [HEIGHT]) <=300, "A1",
IF(VALUE(Sheet1[LENGTH])>300 && VALUE(Sheet1[LENGTH]) <=650 && VALUE(Sheet1[WIDTH]) >300 && VALUE(Sheet1[WIDTH]) <=650 && VALUE(Sheet1[HEIGHT]) >300 && VALUE (Sheet1[HEIGHT]) <=650, "A2",
IF(VALUE(Sheet1[LENGTH])>650 && VALUE(Sheet1[LENGTH]) <=900 && VALUE(Sheet1[WIDTH]) >650 && VALUE(Sheet1[WIDTH]) <=900 && VALUE(Sheet1[HEIGHT]) >650 && VALUE (Sheet1[HEIGHT]) <=900, "A3",
IF(VALUE(Sheet1[LENGTH])>900 && VALUE(Sheet1[LENGTH]) <=1200 && VALUE(Sheet1[WIDTH]) >900 && VALUE(Sheet1[WIDTH]) <=1200 && VALUE(Sheet1[HEIGHT]) >900 && VALUE(Sheet1[HEIGHT]) <=1200, "A4",
IF(VALUE(Sheet1[LENGTH])>1200 && VALUE(Sheet1[WIDTH]) >1200 && VALUE(Sheet1[HEIGHT]) >1200 , "XXX",
"Others"))))))
Result:
I don't get the error in my code. I try to compare a buffer of unsigned char values to a constant. Then I want to store 1 or 0 depending on the comparison. Here is my code (in a structure):
void operator()(const uint8* src, int32 swidth, int32 sheight, uint8* dst, uint8 value) {
uint8 t[16];
__m128i v_one = _mm_set1_epi8((uint8)1);
__m128i v_value = _mm_set1_epi8(value);
printf("value = %d\n", value);
SHOW(t, v_one);
SHOW(t, v_value);
std::cout << "****" << std::endl;
for (int32 i = 0; i < sheight; ++i) {
const uint8* sdata = src + i * swidth;
uint8* ddata = dst + i * swidth;
int32 j = 0;
for ( ; j <= swidth - 16; j += 16) {
__m128i s = _mm_load_si128((const __m128i*)(sdata + j));
__m128i mask = _mm_cmpgt_epi8(s, v_value);
SHOW(t, s);
SHOW(t, mask);
std::cout << std::endl;
}
}
}
My first line are what I would expect:
value = 100
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
But then my comparison are wrong:
214 100 199 203 232 50 85 195 70 141 121 160 93 130 242 233
0 0 0 0 0 0 0 0 0 0 255 0 0 0 0 0
And I really don't get where the mistakes are.
The SHOW macro is:
#define SHOW(t, r) \
_mm_storeu_si128((__m128i*)t, r); \
printf("%3d", (int32)t[0]); \
for (int32 k = 1; k < 16; ++k) \
printf(" %3d", (int32)t[k]); \
printf("\n")
You are comparing the elements in your s array with your value array.
All the values in the value array are 100.
You have a mix of values in your s array.
However, _mm_cmpgt_epi8 works on signed values and as these are bytes it considers values from -128 to +127.
So the only possible values that are > 100 are values in the range 101 to 127.
As you've only got 1 value in that range (121) thats the only one which has its mask set.
To see this, change uint8 t[16]; to int8 t[16]; and you should get a more expected result.
I am trying to parallelize a for(){...} loop, using OpenMP, which takes a number of "lines" N of a "table" N*M and sorts each line in an ascending order.
I added #pragma omp parallel, #pragma omp for schedule directives, but don't see any changes, as if it does nothing at all.
Here is full program:
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <iostream>
double GetTime() {
struct timeval clock;
gettimeofday(&clock, NULL);
double rez = (double)clock.tv_sec+(double)clock.tv_usec/1000000;
return rez;
}
void genMatrix(int *A, int N, int M) {
// Generate matrix
for (int i=0; i<N; i++) {
for (int j=0; j<M; j++) A[i*M+j] = (int)((double)rand()/RAND_MAX*99) + 1;
}
}
int main() {
srand(time(NULL));
int N = 4800;
int M = 6000;
int *A = new int[N*M];
int t, n;
genMatrix(A, N, M);
double t_start = GetTime();
#pragma omp parallel
{
#pragma omp for schedule
for (int k=0; k<N; k++) {
for (int i=0; i<M-1; i++) {
for (int j=0; j<M-1; j++) {
if (A[k*M+j] > A[k*M+j+1]) {
t = A[k*M+j];
A[k*M+j] = A[k*M+j+1];
A[k*M+j+1] = t;
}}}}}
double t_load = GetTime();
// Print matrix
// for (int i=0; i<N; i++) {
// for (int j=0; j<M; j++) {
// printf("%3d", A[i*M+j]);
// }
// printf("\n");
// }
printf("Load time: %.2f\n", t_load - t_start);
system("pause");
}
What is wrong and how should I add parallelization with OpenMP in this case?
Also, don't know why, but when trying to print the matrix A with big numbers( like int N = 480;int M = 600; ), some values are not sorted.
Is it a printing problem?
There are three distinct things, sine-qua-non, to go omp parallel:
A ) - the algorithm has to be correct
B ) - the algorithm has to use resources efficiently
C ) - the algorithm has to spend less on add-on overhead costs, than it receives from going omp
Fixing A) and after some slight experimentation on B) and C):
one may soon realise, that the costs demonstrated under B ) and C ) for a rand() processing are way higher, that any benefit from whatever naive or smarter matrix-coverage mapping onto resources ( here, a singular-engine, as any type of concurrency has to re-propagate a new state of the rand()-source-of-randomness across all the concurrent uses thereof, costs way more than it could deliver in concurrently operated matrix-coverage ( plus naive cache-line un-aware crossing of the matrix does not help either ).
The best results ( without optimising the myOMP_SCHEDULE_CHUNKS ):
/*
-O3 private( ..., i, j ) omp single
MATRIX.RAND time: 3 191 [us] 3 446 [us] 3 444 [us] 3 384 [us] 3 173 [us]
MATRIX.SORT time: 96 270 [us] 98 401 [us] 98 423 [us] 95 911 [us] 101 019 [us] #( 3 ) = OMP_THREADS in [ 5 ] OMP_SCHEDULE_CHUNKS
*/
The global view:
/* COMPILE:: -fopenmp
*
* MAY SHELL:: $ export OMP_NUM_THREADS = 3
* $ export OMP_DISPLAY_ENV = 1
* https://stackoverflow.com/questions/47495916/how-to-parallelize-matrix-sorting-for-loop
*/
#include <omp.h>
#define myOMP_SCHEDULE_CHUNKS 5 // OMP schedule( static, chunk ) ~ better cache-line depletion
#define myOMP_THREADS 4
/*
$ ./OMP_matrix_SORT
MATRIX.RAND time: 187 744 [us] 234 729 [us] 174 535 [us] 254 273 [us] 122 983 [us]
MATRIX.SORT time: 1 911 310 [us] 1 898 494 [us] 2 026 455 [us] 1 978 631 [us] 1 911 231 [us] #( 3 ) = OMP_THREADS
MATRIX.RAND time: 6 166 [us] 6 977 [us] 6 722 [us]
MATRIX.SORT time: 2 448 608 [us] 2 264 572 [us] 2 355 366 [us] #( 3 ) = OMP_THREADS in [ 5 ] OMP_SCHEDULE_CHUNKS
MATRIX.RAND time: 6 918 [us] 17 551 [us] 7 194 [us]
MATRIX.SORT time: 1 774 883 [us] 1 809 002 [us] 1 786 494 [us] #( 1 ) = OMP_THREADS
MATRIX.RAND time: 7 321 [us] 7 337 [us] 6 698 [us]
MATRIX.SORT time: 2 152 945 [us] 1 900 149 [us] 1 883 638 [us] #( 1 ) = OMP_THREADS
MATRIX.RAND time: 54 198 [us] 67 290 [us] 52 123 [us]
MATRIX.SORT time: 759 248 [us] 769 580 [us] 760 759 [us] 812 875 [us] #( 3 ) = OMP_THREADS
MATRIX.RAND time: 7 054 [us] 6 414 [us] 6 435 [us] 6 426 [us]
MATRIX.SORT time: 687 021 [us] 760 917 [us] 674 496 [us] 705 629 [us] #( 3 ) = OMP_THREADS
-O3
MATRIX.RAND time: 5 890 [us] 6 147 [us] 6 081 [us] 5 796 [us] 6 143 [us]
MATRIX.SORT time: 148 381 [us] 152 664 [us] 184 922 [us] 155 236 [us] 169 442 [us] #( 3 ) = OMP_THREADS in [ 5 ] OMP_SCHEDULE_CHUNKS
-O3 private( ..., i, j )
MATRIX.RAND time: 6 410 [us] 6 111 [us] 6 903 [us] 5 831 [us] 6 224 [us]
MATRIX.SORT time: 129 787 [us] 129 836 [us] 195 299 [us] 136 111 [us] 161 117 [us] #( 4 ) = OMP_THREADS in [ 5 ] OMP_SCHEDULE_CHUNKS
MATRIX.RAND time: 6 349 [us] 6 532 [us] 6 104 [us] 6 213 [us]
MATRIX.SORT time: 151 202 [us] 152 542 [us] 160 403 [us] 180 375 [us] #( 3 ) = OMP_THREADS in [ 5 ] OMP_SCHEDULE_CHUNKS
MATRIX.RAND time: 6 745 [us] 5 834 [us] 5 791 [us] 7 164 [us] 6 535 [us]
MATRIX.SORT time: 214 590 [us] 214 563 [us] 209 610 [us] 205 940 [us] 230 787 [us] #( 2 ) = OMP_THREADS in [ 5 ] OMP_SCHEDULE_CHUNKS
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <iostream>
long GetTime() { // double GetTime()
struct timeval clock;
gettimeofday( &clock, NULL );
return (long)clock.tv_sec * 1000000 // in [us] ( go (long) instead of float )
+ (long)clock.tv_usec; //
/* double rez = (double)clock.tv_sec
* + (double)clock.tv_usec / 1000000;
* // + (double)clock.tv_usec * 0.000001; // NEVER DIV
return rez;
*/
}
void genMatrix( int *A, int N, int M ) { // Generate matrix
register int i, iM, j;
#pragma omp parallel
for ( i = 0; i < N; i++ ) {
iM = i * M;
/* for ( register int i = 0; i < N; i++ ) {
register int iM = i * M;
*/
// #pragma omp parallel // 234 729 [us]
// for ( register int j = 0; j < M; j++ )
// #pragma omp parallel for schedule( static, myOMP_SCHEDULE_CHUNKS ) // 122 983 [us] #( 3 ) = OMP_THREADS ~~~ v/s 6 698 [us] #( 1 ) = OMP_THREADS
// // v/s 5 796 [us] # NON-OMP
#pragma omp single // ~~ 3 191 [us]
for ( int j = 0; j < M; j++ )
A[iM +j] = (int)( (double)rand() / RAND_MAX * 99 ) + 1;
// A[i*M+j] = (int)( (double)rand() / RAND_MAX * 99 ) + 1;
}
}
int main() {
srand( time( NULL ) );
int N = 480; // 4800; ~ 100x faster outputs
int M = 600; // 6000;
int Mb1 = M - 1;
int *A = new int[N*M];
omp_set_num_threads( myOMP_THREADS );
long long int t_start = GetTime();
genMatrix( A, N, M );
long long int t_load = GetTime();
printf( "MATRIX.RAND time: %lld [us]\n", t_load - t_start );
register int thisB,
this1,
next1,
t, i, j;
t_start = GetTime(); // double t_start = GetTime();
// for ( register int k = 0; k < N; k++ ) {
// #pragma omp parallel
// #pragma omp parallel for schedule( static, myOMP_SCHEDULE_CHUNKS ) // schedule( type, chunk ):
// #pragma omp parallel for schedule( static, myOMP_SCHEDULE_CHUNKS ) private( thisB, this1, next1, t ) // schedule( type, chunk ):
#pragma omp parallel for schedule( static, myOMP_SCHEDULE_CHUNKS ) private( thisB, this1, next1, t, i, j ) // schedule( type, chunk ):
for ( int k = 0; k < N; k++ ) {
thisB = k*M;
if ( omp_get_num_threads() != myOMP_THREADS ) {
printf( "INF: myOMP_THREADS ( == %d ) do not match the number of executed ones ( == %d ) ", myOMP_THREADS, omp_get_num_threads() );
}
//--------------------------------------------------// -------------SORT ROW-k
// for ( register int i = 0; i < Mb1; i++ ) { // < M-1; i++ ) {
// for ( register int j = 0; j < Mb1; j++ ) { // < M-1; j++ ) {
for ( i = 0; i < Mb1; i++ ) {
for ( j = 0; j < Mb1; j++ ) {
this1 = thisB + j,
next1 = this1 + 1;
if ( A[this1] > A[next1] ){ // A[k*M+j ] > A[k*M+j+1] ) {
t = A[this1]; // t = A[k*M+j ];
A[this1] = A[next1]; // A[k*M+j ] = A[k*M+j+1];
A[next1] = t; // A[k*M+j+1] = t;
}
}
}
//--------------------------------------------------// -------------SORT ROW-k
}
t_load = GetTime(); // double t_load = GetTime();
/* Print matrix
//
for ( int i = 0; i < N; i++ ) {
for ( int j = 0; j < M; j++ ) {
printf( "%3d", A[i*M+j] );
}
printf("\n");
}
//
*/
printf( "MATRIX.SORT time: %lld [us] #( %d ) = OMP_THREADS in [ %d ] OMP_SCHEDULE_CHUNKS\n",
t_load - t_start,
myOMP_THREADS,
myOMP_SCHEDULE_CHUNKS
);
// system( "pause" );
}
After going over this tutorial
http://tommd.github.io/
which uses the HElib library:
https://github.com/shaih/HElib
I get the following output:
The output is getting corrupted. Given that the example has Level 16, there should be plenty of room to perform these operations.
Is there a problem with the parameters ?
Code:
#include "FHE.h"
#include "EncryptedArray.h"
#include <NTL/lzz_pXFactoring.h>
#include <fstream>
#include <sstream>
#include <sys/time.h>
using namespace std;
/**
*
*/
int main(int argc, char** argv) {
/* On our trusted system we generate a new key
* (or read one in) and encrypt the secret data set.
*/
long m=0, p=2, r=1; // Native plaintext space
// Computations will be 'modulo p'
long L=16; // Levels
long c=3; // Columns in key switching matrix
long w=64; // Hamming weight of secret key
long d=0;
long security = 128;
ZZX G;
m = FindM(security,L,c,p, d, 0, 0);
FHEcontext context(m, p, r);
// initialize context
buildModChain(context, L, c);
// modify the context, adding primes to the modulus chain
FHESecKey secretKey(context);
// construct a secret key structure
const FHEPubKey& publicKey = secretKey;
// an "upcast": FHESecKey is a subclass of FHEPubKey
//if(0 == d)
G = context.alMod.getFactorsOverZZ()[0];
secretKey.GenSecKey(w);
// actually generate a secret key with Hamming weight w
addSome1DMatrices(secretKey);
cout << "Generated key" << endl;
EncryptedArray ea(context, G);
// constuct an Encrypted array object ea that is
// associated with the given context and the polynomial G
long nslots = ea.size();
vector<long> v1;
for(int i = 0 ; i < nslots; i++) {
v1.push_back(i*2);
}
Ctxt ct1(publicKey);
ea.encrypt(ct1, publicKey, v1);
vector<long> v2;
Ctxt ct2(publicKey);
for(int i = 0 ; i < nslots; i++) {
v2.push_back(i*3);
}
ea.encrypt(ct2, publicKey, v2);
// On the public (untrusted) system we
// can now perform our computation
Ctxt ctSum = ct1;
Ctxt ctProd = ct1;
ctSum += ct2;
ctProd *= ct2;
vector<long> res;
ea.decrypt(ctSum, secretKey, res);
cout << "All computations are modulo " << p << "." << endl;
for(int i = 0; i < res.size(); i ++) {
cout << v1[i] << " + " << v2[i] << " = " << res[i] << endl;
}
ea.decrypt(ctProd, secretKey, res);
for(int i = 0; i < res.size(); i ++) {
cout << v1[i] << " * " << v2[i] << " = " << res[i] << endl;
}
return 0;
}
Generated key
All computations are modulo 2.
0 + 0 = 0
2 + 3 = 1
4 + 6 = 0
6 + 9 = 1
8 + 12 = 0
10 + 15 = 1
12 + 18 = 0
14 + 21 = 1
16 + 24 = 0
18 + 27 = 1
20 + 30 = 0
22 + 33 = 1
24 + 36 = 0
26 + 39 = 1
28 + 42 = 0
30 + 45 = 1
32 + 48 = 0
34 + 51 = 1
36 + 54 = 0
38 + 57 = 1
40 + 60 = 0
42 + 63 = 1
44 + 66 = 0
46 + 69 = 1
48 + 72 = 0
50 + 75 = 1
52 + 78 = 0
54 + 81 = 1
56 + 84 = 0
58 + 87 = 1
60 + 90 = 0
... Some sum output omitted
0 * 0 = 0
2 * 3 = 0
4 * 6 = 0
6 * 9 = 0
8 * 12 = 0
10 * 15 = 0
12 * 18 = 0
14 * 21 = 0
16 * 24 = 0
18 * 27 = 0
20 * 30 = 0
22 * 33 = 0
24 * 36 = 0
26 * 39 = 0
28 * 42 = 0
30 * 45 = 0
32 * 48 = 0
34 * 51 = 0
36 * 54 = 0
38 * 57 = 0
40 * 60 = 0
42 * 63 = 0
44 * 66 = 0
46 * 69 = 0
48 * 72 = 0
50 * 75 = 0
52 * 78 = 0
54 * 81 = 0
56 * 84 = 0
58 * 87 = 0
60 * 90 = 0
62 * 93 = 0
64 * 96 = 0
66 * 99 = 0
68 * 102 = 0
70 * 105 = 0
72 * 108 = 0
74 * 111 = 0
76 * 114 = 0
78 * 117 = 0
80 * 120 = 0
82 * 123 = 0
84 * 126 = 0
86 * 129 = 0
....
Ah, so this is a misunderstanding of the operations being performed. Notice the constant p=2. I have the text All computations are modulo 2.. Perhaps also stating All inputs are modulo 2 would help hammer the point home. Lets look at some of our computations:
0 + 0 mod 2 = 0
2 + 3 mod 2 = 1
4 + 6 mod 2 = 0
6 + 9 mod 2 = 1
All looks good - addition ring 2 is just exclusive OR. How about multiplication? In ring 2 (binary) that's just AND:
0 * 0 = 0
2 * 3 = 6 mod 2 = 0
4 * 6 = 24 mod 2 = 0
6 * 9 = 54 mod 2 = 0
So that all checks out as well. Finally, look back at the blog and see that I called this out again and give you a way to operate on something you might consider more pleasing:
In this case, I am building for GF(2) - so my homormorphic addition
is XOR and multiplication is AND. Changing this is as easy as changing
the value of p. Folks wanting to see 2+2=4 should set p to something
that matches their desired domain, such as 257 to obtain 8 bit Ints.
However, HELib has regressed in this aspect - setting p equal to anything larger than 2 did not work last time I tried it. Shai confirmed this is a known regression.
I've been following a paper which at some stage mentions 'calculating the gradient over a 5x5 neighbourhood'. However, the supplementary code simply uses gradient(I, 2, 2). As far as I'm aware that just makes the step size 2 but still computes the gradient using central finite difference between 2 adjacent points (for each direction) but divides by 2 instead (please tell me if I'm wrong here).
So, instead I assume perhaps that computing the gradient via sobel for 5x5 makes more sense.
However, I'm doing this in 3D so I have been trying to write a 3D convolution function (note: I don't want to use libraries for this or the FFT method. Speed isn't a problem here).
typedef boost::multi_array<float, 3> array_type;
typedef array_type::index index;
float convolve3D(const array_type& input, int x, int y, int z, int iWidth, int iHeight, int iDepth, const array_type& kernel, int kernelSize)
{
auto isOutsidePixel = [&](int xPos, int yPos, int zPos)->int
{
if(xPos >= 0 && xPos < iWidth && yPos >= 0 && yPos < iHeight && zPos >= 0 && zPos < iDepth)
{
return false;
}
else
{
return true;
}
};
float result = 0.0f;
int xPos, yPos, zPos;
int filterSize = 3;
for(int k = 0; k < kernelSize; k++)
{
for(int j = 0; j < kernelSize; j++)
{
for(int i = 0; i < kernelSize; i++)
{
xPos = x + i-(kernelSize/2);
yPos = y + j-(kernelSize/2);
zPos = z + k-(kernelSize/2);
if(isOutsidePixel(xPos, yPos, zPos) == false)
{
result += kernel[i][j][k] * input[xPos][yPos][zPos];
}
}
}
}
return result;
}
I then feed this function some test data to test on just the x kerenel to get the x component:
x_kernel[0][0][0] = -1.0f; x_kernel[1][0][0] = 0.0f; x_kernel[2][0][0] = 1.0f;
x_kernel[0][1][0] = -2.0f; x_kernel[1][2][0] = 0.0f; x_kernel[2][3][0] = 2.0f;
x_kernel[0][2][0] = -1.0f; x_kernel[1][2][0] = 0.0f; x_kernel[2][2][0] = 1.0f;
x_kernel[0][0][1] = -2.0f; x_kernel[1][0][1] = 0.0f; x_kernel[2][0][1] = 2.0f;
x_kernel[0][4][1] = -4.0f; x_kernel[1][5][1] = 0.0f; x_kernel[2][6][1] = 4.0f;
x_kernel[0][2][1] = -2.0f; x_kernel[1][2][1] = 0.0f; x_kernel[2][2][1] = 2.0f;
x_kernel[0][0][2] = -1.0f; x_kernel[1][0][2] = 0.0f; x_kernel[2][0][2] = 1.0f;
x_kernel[0][7][2] = -2.0f; x_kernel[1][8][2] = 0.0f; x_kernel[2][9][2] = 2.0f;
x_kernel[0][2][2] = -1.0f; x_kernel[1][2][2] = 0.0f; x_kernel[2][2][2] = 1.0f;
with my image being
I[0][0][0] = 5; I[0][10][0] = 30; I[0][2][0] = 20;
I[1][0][0] = 10; I[1][11][0] = 10; I[1][2][0] = 5;
I[2][0][0] = 20; I[2][12][0] = 5; I[2][2][0] = 100;
I[0][0][1] = 500; intensityArray2[0][13][1] = 50; intensityArray2[0][2][1] = 70;
I[1][0][1] = 200; intensityArray2[1][14][1] = 5; intensityArray2[1][2][1] = 75;
I[2][0][1] = 100; intensityArray2[2][15][1] = 10; intensityArray2[2][2][1] = 45;
I[0][0][2] = 400; I[0][16][2] = 90; I[0][2][2] = 30;
I[1][0][2] = 50; I[1][17][2] = 100; I[1][2][2] = 45;
I[2][0][2] = 20; I[2][18][2] = 90; I[2][2][2] = 60;
I get the following result:
465 , -830 , -465 ,
355 , -415 , -355 ,
195 , 180 , -195 ,
1040 , -2435 , -1040 ,
900 , -1315 , -900 ,
520 , 15 , -520 ,
805 , -2360 , -805 ,
875 , -1205 , -875 ,
535 , 30 , -535 ,
In MATLAB I then replicate the same kernel and image.
k(:,:,1) = [-1 0 1; -2 0 2; -1 0 1];
k(:,:, 2) = [-2 0 2; -4 0 4 ; -2 0 2];
k(:,:,3) = [-1 0 1; -2 0 2; -1 0 1];
I(:,:,1) = [5 30 20; 10 10 5; 20 5 100];
I(:, :, 2) = [500 50 70; 200 5 75; 100 10 45];
I(:,:,3) = [400 90 30; 50 100 45; 20, 90, 60];
convn(I,k)
and get the following result.
ans(:,:,1) =
-5 -30 -15 30 20
-20 -70 -25 70 45
-45 -55 -85 55 130
-50 -20 -155 20 205
-20 -5 -80 5 100
ans(:,:,2) =
-510 -110 400 110 110
-1240 -245 935 245 305
-1090 -180 565 180 525
-500 -65 -75 65 575
-140 -20 -105 20 245
ans(:,:,3) =
-1405 -220 1215 220 190
-3270 -560 2690 560 580
-2565 -575 1725 575 840
-940 -350 240 350 700
-240 -115 -10 115 250
ans(:,:,4) =
-1300 -230 1170 230 130
-2900 -665 2475 665 425
-2040 -830 1415 830 625
-580 -585 85 585 495
-140 -190 -25 190 165
ans(:,:,5) =
-400 -90 370 90 30
-850 -280 745 280 105
-520 -380 340 380 180
-90 -280 -75 280 165
-20 -90 -40 90 60
The central pixels (I'm not concerned about the added extra image size bits) don't seem to be matching up. This method worked for 2D and I just expanded it to 3D. Is there anything immediately obvious that I've done wrong?
Thanks