GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
/* last change: 16.03.01 by Oliver Heidbuechel */1234#include <typedef.h>5#include <matrix.h>6#include <bravais.h>7#include <base.h>8#include <graph.h>9#include <zass.h>10#include <datei.h>11#include <longtools.h>12#include <sort.h>13#include <presentation.h>141516typedef struct{17int **x;18int ***l;19int ***o;20} SOL_TYP;21222324/* ----------------------------------------------------------------------------- */25static SOL_TYP *init_SOL_TYP(int gitter_no,26int aff_i,27int aff_j,28boolean oflag)29{30int i, j;3132SOL_TYP *sol;33343536sol = (SOL_TYP *)calloc(gitter_no, sizeof(SOL_TYP));3738for (i = 0; i < gitter_no; i++){39sol[i].x = (int **)calloc(aff_i, sizeof(int *));40sol[i].l = (int ***)calloc(aff_i, sizeof(int **));41if (oflag)42sol[i].o = (int ***)calloc(aff_i, sizeof(int **));43for (j = 0; j < aff_i; j++){44sol[i].x[j] = (int *)calloc(aff_j, sizeof(int));45sol[i].l[j] = (int **)calloc(aff_j, sizeof(int *));46if (oflag)47sol[i].o[j] = (int **)calloc(aff_j, sizeof(int *));48}49}5051return(sol);52}53545556/* ----------------------------------------------------------------------------- */57static void free_SOL_TYP(SOL_TYP *sol,58int gitter_no,59int aff_i,60int aff_j)61{62int i, j, k;6364for (i = 0; i < gitter_no; i++){65for (j = 0; j < aff_i; j++){66for (k = 0; k < aff_j; k++){67if (sol[i].l[j][k] != NULL)68free(sol[i].l[j][k]);69if (sol[i].o != NULL && sol[i].o[j] != NULL && sol[i].o[j][k] != NULL)70free(sol[i].o[j][k]);71}72free(sol[i].l[j]);73free(sol[i].x[j]);74if (sol[i].o != NULL && sol[i].o[j] != NULL)75free(sol[i].o[j]);76}77free(sol[i].l);78free(sol[i].x);79if (sol[i].o != NULL)80free(sol[i].o);81}82free(sol);83}84858687/* ----------------------------------------------------------------------------- */88static boolean gibt_gitter_beitrag(int *gitter_no,89int laenge,90int no)91{92int i;9394for (i = 1 ; i <= laenge; i++){95if (gitter_no[i] == no)96return (TRUE);97}98return (FALSE);99}100101102103/* ----------------------------------------------------------------------------- */104/* test if two groups are equal */105/* ----------------------------------------------------------------------------- */106static int test_fkt(bravais_TYP *t,107bravais_TYP *G)108{109int i, j, k, counter, flagge, ret;110111matrix_TYP **Gorbit, *tmp;112113114Gorbit = (matrix_TYP **)calloc(G->order, sizeof(matrix_TYP *));115Gorbit[0] = init_mat(t->dim, t->dim, "1");116counter = 1;117i = 0;118119while (counter < G->order){120for (j = 0; j < G->gen_no; j++){121tmp = mat_mul(Gorbit[i], G->gen[j]);122flagge = 1;123for (k = 0; k < counter && flagge != 0; k++){124flagge = cmp_mat(tmp, Gorbit[k]);125}126if (flagge != 0){127Gorbit[counter] = tmp;128counter++;129}130else{131free_mat(tmp);132}133}134i++;135}136137ret = 1;138for (i = 0; i < t->gen_no; i++){139flagge = 0;140for (j = 0; j < G->order; j++){141if (cmp_mat(Gorbit[j], t->gen[i]) == 0){142flagge = 1;143break;144}145}146if (flagge == 0){147ret = 0;148break;149}150}151152for (i = 0; i < G->order; i++){153free_mat(Gorbit[i]);154}155free(Gorbit);156157return(ret);158}159160161162/* ----------------------------------------------------------------------------- */163/* calculate graph of incidences for k-subgroups for a given geometric class */164/* beeing not 1 or -1! */165/* ----------------------------------------------------------------------------- */166matrix_TYP *subgroupgraph(Q_data_TYP *data,167boolean oflag)168{169int i, j, k, l, m, q, flagge, reps_no,170image_gen_no, S1_word_no, norm_no, kernel_order, orbit_no,171*kernel_list, *orbit_length, *length,172***WORDS, *WORDS_no,173i__, j__, counter, translanz, *kernel_factor,174lattice_orbits_no, *lattice_orbits, *lattice_orbit_length,175**gitter_no, *smallest, i__first, reps_flag,176*primes, *exponent, *konj_wort;177178QtoZ_entry_TYP entry;179180matrix_TYP *erg,181*id,182*lattice,183*invlattice,184*diag,185*phi,186*kernel_mat,187**kernel_gen,188**kernel_elements,189**image,190**lNli,191**S1,192**S1_inv,193**S_ksi,194***dataNinv,195**orbit_rep,196**new_rep,197***reps,198*coz_j,199*coz_i,200*cocycle,201**translationen,202**TRASH;203204word *relator;205206bravais_TYP *G;207208H1_mod_ker_TYP H1_mod_ker;209210SOL_TYP *zwischenerg;211212rational eins;213214215216eins.z = eins.n = 1;217218dataNinv = (matrix_TYP ***)calloc(data->Z_no, sizeof(matrix_TYP **));219for (i = 0; i < data->Z_no; i++){220dataNinv[i] = (matrix_TYP **)calloc(data->Z[i]->normal_no, sizeof(matrix_TYP *));221}222id = init_mat(data->G->dim, data->G->dim, "1");223erg = init_mat(data->all, data->all, "");224225/* convert presentation into relator format */226relator = (word *) calloc(data->pres->rows,sizeof(word));227for (i = 0; i < data->pres->rows; i++){228matrix_2_word(data->pres, relator + i, i);229}230231for (i = 0; i < data->Z_no; i++){232233translationen = transl_aff_normal(data->Z[i]->gen, data->Z[i]->gen_no, &translanz);234235for (j = 0; j < data->Z_no; j++){236entry = data->INZ->entry[i][j];237zwischenerg = init_SOL_TYP(entry.anz, data->aff_no[i], data->aff_no[j], oflag);238gitter_no = (int **)calloc(data->aff_no[i], sizeof(int *));239for (k = 0; k < data->aff_no[i]; k++){240gitter_no[k] = (int *)calloc(entry.anz + 1, sizeof(int));241}242kernel_factor = (int *)calloc(entry.anz, sizeof(int));243primes = (int *)calloc(entry.anz, sizeof(int));244exponent = (int *)calloc(entry.anz, sizeof(int));245for (k = 0; k < entry.anz; k++){246lattice = entry.lattice[k];247248/* calculate index of the sublattice */249for (l = 0; l < lattice->rows; l++){250if (entry.lsf[k]->array.SZ[l][l] != 1){251primes[k] = entry.lsf[k]->array.SZ[l][l];252exponent[k]++;253}254}255256invlattice = mat_inv(lattice);257diag = matrix_on_diagonal(lattice, data->G->gen_no);258259/* calculate information about Ker phi | B^1 */260TRASH = kernel_factor_fct(translationen, translanz, data->Z[i]->gen_no, lattice,261&kernel_factor[k]);262for (l = 0; l < kernel_factor[k]; l++){263free_mat(TRASH[l]);264}265free(TRASH);266267/* test if lattice^(-1) data->Z[i]->gen[l] lattice == data->Z[j]->gen[l] */268flagge = 1;269G = konj_bravais(data->Z[i], invlattice);270if (GRAPH_DEBUG){271if (!test_fkt(G, data->Z[j])){272fprintf(stderr, "ERROR 1 in subgroupgraph!\n");273exit(8);274}275}276for (l = 0; l < G->gen_no; l++){277if (cmp_mat(data->Z[j]->gen[l], G->gen[l]) != 0){278flagge = 0;279break;280}281}282283/* calculate phi: H^1(Z[i], Q^n/lattice) -> H^1(Z[i], Q^n/Z^n) */284if (flagge == 0){285cocycle = H1_of_standard_to_GL(G, data->Z[j], data->X[j]);286calculate_phi(diag, cocycle, data->X[i], data->X[j], data->X_2_inv[i], &phi,287&kernel_mat, &image, &image_gen_no, &H1_mod_ker);288free_mat(cocycle);289}290else{291calculate_phi(diag, data->X[j][0], data->X[i], data->X[j], data->X_2_inv[i], &phi,292&kernel_mat, &image, &image_gen_no, &H1_mod_ker);293}294kernel_gen = col_to_list(kernel_mat);295kernel_elements = (matrix_TYP **)calloc(data->coho_size[j], sizeof(matrix_TYP *));296kernel_list = aufspannen(data->coho_size[j], kernel_elements, kernel_gen,297kernel_mat->cols, data->X[j][1], &kernel_order);298free_bravais(G);299300/* calculate S1 = Stab_N(L)*/301if (phi->cols > 0){302norm_no = data->Z[j]->normal_no;303lNli = (matrix_TYP **)calloc(norm_no, sizeof(matrix_TYP *));304for (l = 0; l < norm_no; l++){305lNli[l] = mat_kon(lattice, data->Z[j]->normal[l], invlattice);306}307308S1 = calculate_S1(id, lNli, norm_no, &S1_word_no,309data->N[j], dataNinv[j], data->X[j][1]);310311S1_inv = (matrix_TYP **)calloc(S1_word_no, sizeof(matrix_TYP *));312for (l = 0; l < norm_no; l++){313free_mat(lNli[l]);314}315free(lNli);316}317else{318/* trivial part */319S1_word_no = 0;320}321322if (H1_mod_ker.flag == 0 && H1_mod_ker.erz_no > 0){323/* representation from S1 on H^1(G,Q^n/lattice) / Ker(phi) */324new_rep = new_representation(S1, S1_word_no, H1_mod_ker, data->X[j][1]);325326/* orbit on H^1(G,Q^n/lattice) / Ker(phi) */327reps = H1_mod_ker_orbit_alg(H1_mod_ker, new_rep, S1_word_no, &reps_no, &length,328&WORDS, &WORDS_no, NULL);329330/* l = 0 (d.h. Untergruppen der zerfallenden Gruppe) */331/* orbit on 0 + Ker(phi): l = 0 */332orbit_rep = orbit_ker(kernel_elements, kernel_order, data->X[j][1], S1,333S1_word_no, data->coho_size[j], kernel_list, &orbit_no,334&orbit_length);335336/* edges in the graph */337i__ = data->first_aff[i];338if (orbit_no > 0){339gitter_no[0][0]++;340gitter_no[0][gitter_no[0][0]] = k;341}342343for (m = 0; m < orbit_no; m++){344j__ = number_of_affine_class(data, orbit_rep[m], j, 0, oflag, &konj_wort);345zwischenerg[k].x[0][j__]++;346if (zwischenerg[k].l[0][j__] == NULL){347zwischenerg[k].l[0][j__] = (int *)calloc(orbit_no + 1, sizeof(int));348}349if (oflag && zwischenerg[k].o[0][j__] == NULL){350zwischenerg[k].o[0][j__] = (int *)calloc(orbit_no + 1, sizeof(int));351}352zwischenerg[k].l[0][j__][0]++;353zwischenerg[k].l[0][j__][ zwischenerg[k].l[0][j__][0] ] =354orbit_length[m];355if (oflag){356zwischenerg[k].o[0][j__][0]++;357zwischenerg[k].o[0][j__][ zwischenerg[k].o[0][j__][0] ] =358obergruppenzahl(invlattice, data->Z[j]->normal,359data->norm_inv[j], data->stab_coz[j][j__],360data->stab_gen_no[j][j__], konj_wort);361free(konj_wort);362}363}364free(orbit_length);365for (m = 0; m < orbit_no; m++){366free_mat(orbit_rep[m]);367}368free(orbit_rep);369370371/* l > 0 (d.h. Untergruppen der nicht zerfallenden Gruppen) */372/* orbit on ksi + Ker(phi): l = 0 */373kernel_elements_2_affine(kernel_elements, data->coho_size[j]);374375for (l = 1; l < reps_no; l++){376/* welcher Repraesentant ist Untergruppe des377Standardvertreter einer affinen Klasse (welcher?)? */378reps_flag = 0;379for (m = 0; m < length[l]; m++){380coz_i = mat_mul(phi, reps[l][m]);381i__ = number_of_affine_class(data, coz_i, i, 1, FALSE, NULL);382free_mat(coz_i);383if (m == 0)384i__first = i__;385if (abs(i__first) != abs(i__)){386/* paranoia test */387fprintf(stderr, "ERROR 2 in subgroupgraph!\n");388exit(9);389}390if (i__ > 0){391reps_flag = 1;392/* break; */393}394}395396if (reps_flag != 1){397/* printf("HHHHHHHHHHHHHHHHHHHHH\n"); */398/* Die Gruppen U_{l,m}, die gegeben sind durch reps[l][m],399sind Untergruppen einer Raumgruppe R, die nicht der400Standardvertreter S der affinen Klasse ist (fuer alle m)!401Es sei n mit R^n = S. Dann ist U_l^n Untergruppe402von S. Diese Gruppen werden bei dem Gitter nL betrachtet,403wobei L das aktuell betrachtete Gitter sei. L und nL sind404offensichtlich nicht in einer Bahn unter der Punktgruppe405des affinen Nomalisators von S, d.h. unter dem Stabilisator406des Coykels von S. */407}408else{409i__ = abs(i__); /* nur noetig, wenn break auskommentiert */410411/* consider only standard representatives */412counter = 0;413S_ksi = (matrix_TYP **)calloc(WORDS_no[l], sizeof(matrix_TYP *));414for (m = 0; m < WORDS_no[l]; m++){415/* simplify the words */416normalize_word(WORDS[l][m]);417if (WORDS[l][m][0] == 1 && WORDS[l][m][1] < 0)418WORDS[l][m][1] *= (-1);419if (word_already_there(WORDS[l], m) == 0){420S_ksi[counter] = graph_mapped_word(WORDS[l][m], S1, S1_inv, data->X[j][1]);421if (mat_search(S_ksi[counter], S_ksi, counter, mat_comp) != -1){422free_mat(S_ksi[counter]);423}424else{425mat_quicksort(S_ksi, 0, counter, mat_comp);426counter++;427}428}429}430431/* Da es uns nur um Anzahlen geht, koennen wir auch o.B.d.A. Bahnen auf432reps[l][0] + Kern (phi) berechnen */433orbit_rep = orbit_ksi_plus_ker(reps[l][0], kernel_elements, kernel_order,434data->X[j][1], S_ksi, counter,435data->coho_size[j], kernel_list, &orbit_no,436&orbit_length);437438/* edges in tbe graph */439if (gitter_no[i__][gitter_no[i__][0]] != k || gitter_no[i__][0] == 0){440gitter_no[i__][0]++;441gitter_no[i__][gitter_no[i__][0]] = k;442}443for (m = 0; m < orbit_no; m++){444coz_j = mat_add(orbit_rep[m], reps[l][0], eins, eins);445j__ = number_of_affine_class(data, coz_j, j, 0, oflag, &konj_wort);446free_mat(coz_j);447zwischenerg[k].x[i__][j__]++;448if (zwischenerg[k].l[i__][j__] == NULL){449zwischenerg[k].l[i__][j__] = (int *)calloc(orbit_no + 1, sizeof(int));450}451if (oflag && zwischenerg[k].o[i__][j__] == NULL){452zwischenerg[k].o[i__][j__] = (int *)calloc(orbit_no + 1, sizeof(int));453}454zwischenerg[k].l[i__][j__][0]++;455zwischenerg[k].l[i__][j__][ zwischenerg[k].l[i__][j__][0] ] =456orbit_length[m];457if (oflag){458zwischenerg[k].o[i__][j__][0]++;459zwischenerg[k].o[i__][j__][ zwischenerg[k].o[i__][j__][0] ] =460obergruppenzahl(invlattice, data->Z[j]->normal,461data->norm_inv[j], data->stab_coz[j][j__],462data->stab_gen_no[j][j__], konj_wort);463free(konj_wort);464}465}466467/* clean */468free(orbit_length);469for (m = 0; m < orbit_no; m++){470free_mat(orbit_rep[m]);471}472free(orbit_rep);473for (m = 0; m < counter; m++)474free_mat(S_ksi[m]);475free(S_ksi);476}477}478}479else{480/* trivial part */481switch (H1_mod_ker.flag){482case 0:483case 2:484/* orbit on 0 + Ker(phi) */485orbit_rep = orbit_ker(kernel_elements, kernel_order, data->X[j][1], S1,486S1_word_no, data->coho_size[j], kernel_list, &orbit_no,487&orbit_length);488489/* edges in the graph */490i__ = data->first_aff[i];491if (orbit_no > 0){492gitter_no[0][0]++;493gitter_no[0][gitter_no[0][0]] = k;494}495for (m = 0; m < orbit_no; m++){496j__ = number_of_affine_class(data, orbit_rep[m], j, 0, oflag, &konj_wort);497zwischenerg[k].x[0][j__]++;498if (zwischenerg[k].l[0][j__] == NULL){499zwischenerg[k].l[0][j__] = (int *)calloc(orbit_no + 1, sizeof(int));500}501if (oflag && zwischenerg[k].o[0][j__] == NULL){502zwischenerg[k].o[0][j__] = (int *)calloc(orbit_no + 1, sizeof(int));503}504zwischenerg[k].l[0][j__][0]++;505zwischenerg[k].l[0][j__][ zwischenerg[k].l[0][j__][0] ] =506orbit_length[m];507if (oflag){508zwischenerg[k].o[0][j__][0]++;509zwischenerg[k].o[0][j__][ zwischenerg[k].o[0][j__][0] ] =510obergruppenzahl(invlattice, data->Z[j]->normal,511data->norm_inv[j], data->stab_coz[j][j__],512data->stab_gen_no[j][j__], konj_wort);513free(konj_wort);514}515}516free(orbit_length);517for (m = 0; m < orbit_no; m++){518free_mat(orbit_rep[m]);519}520free(orbit_rep);521break;522case 1:523case 3:524zwischenerg[k].x[0][0]++;525zwischenerg[k].l[0][0] = (int *)calloc(2, sizeof(int));526zwischenerg[k].l[0][0][0] = 1;527zwischenerg[k].l[0][0][1] = 1;528if (oflag){529zwischenerg[k].o[0][0] = (int *)calloc(2, sizeof(int));530zwischenerg[k].o[0][0][0] = 1;531zwischenerg[k].o[0][0][1] =532obergruppenzahl(invlattice, data->Z[j]->normal,533data->norm_inv[j], data->stab_coz[j][0],534data->stab_gen_no[j][0], NULL);535}536gitter_no[0][0]++;537gitter_no[0][gitter_no[0][0]] = k;538break;539default:540fprintf(stderr, "ERROR 4 in subgroupgraph!\n");541exit(5);542}543}544545/* clean */546if (H1_mod_ker.flag == 0 && H1_mod_ker.erz_no > 0){547for (l = 0; l < S1_word_no; l++){548free_mat(new_rep[l]);549}550free(new_rep);551for (l = 1; l < reps_no; l++){552for (m = 0; m < WORDS_no[l]; m++){553free(WORDS[l][m]);554}555for (m = 0; m < length[l]; m++){556free_mat(reps[l][m]);557}558free(reps[l]);559free(WORDS[l]);560}561free(WORDS);562free(WORDS_no);563free(reps);564free(length);565}566free_H1_mod_ker_TYP(H1_mod_ker);567for (l = 0; l < data->coho_size[j]; l++){568if (kernel_elements[l] != NULL)569free_mat(kernel_elements[l]);570}571free(kernel_elements);572free(kernel_list);573for (l = 0; l < kernel_mat->cols; l++){574free_mat(kernel_gen[l]);575}576free(kernel_gen);577free_mat(kernel_mat);578for (l = 0; l < image_gen_no; l++){579free_mat(image[l]);580}581if (phi->cols > 0){582for (l = 0; l < S1_word_no; l++){583free_mat(S1[l]);584if (S1_inv[l] != NULL)585free_mat(S1_inv[l]);586}587free(S1);588free(S1_inv);589}590free(image);591free_mat(diag);592free_mat(invlattice);593free_mat(phi);594}595596/* output */597for (k = 0; k < data->aff_no[i] && entry.anz > 1; k++){598599/* mehrere Teilgitter */600if (gitter_no[k][0] > 1){601/* orbit on lattices for each affine class with subgroups from602different lattices */603lattice_orbits = (int *)calloc(entry.anz, sizeof(int));604lattice_orbit_length = (int *)calloc(entry.anz + 1, sizeof(int));605smallest = (int *)calloc(entry.anz + 1, sizeof(int));606/* Stabilisatoren nur bei Bedarf berechnen (get_Q_data und607free_Q_data aendern !!!!!)608if (data->stab_coz[i][k] == NULL){609data->stab_coz[i][k] = stab_coz(data->WORDS[i][k], data->NUMBER_OF_WORDS[i][k],610data->Z[i]->normal, data->norm_inv[i],611data->Z[i]->normal_no, j,612&data->stab_gen_no[i][k]);613}614*/615lattice_orbits_no = orbit_on_lattices(entry.lsf, entry.anz, data->stab_coz[i][k],616data->stab_gen_no[i][k], lattice_orbits,617lattice_orbit_length, smallest, NULL);618619for (l = 1; l <= lattice_orbits_no; l++){620if (gibt_gitter_beitrag(gitter_no[k], gitter_no[k][0], smallest[l])){621printf("%i: ", k + 1 + data->first_aff[i]);622for (m = 0; m < data->aff_no[j]; m++){623if (zwischenerg[smallest[l]].x[k][m] > 0){624for (q = 0; q < zwischenerg[smallest[l]].x[k][m]; q++){625printf("%i (%i, ", m + 1 + data->first_aff[j],626lattice_orbit_length[l] *627zwischenerg[smallest[l]].l[k][m][q + 1] *628kernel_factor[smallest[l]]);629if (oflag)630printf("%i, ", zwischenerg[smallest[l]].o[k][m][q + 1]);631printf("%i^%i) ", primes[smallest[l]], exponent[smallest[l]]);632erg->array.SZ[k + data->first_aff[i]][m + data->first_aff[j]]++;633}634}635}636printf("\n");637}638}639640free(lattice_orbits);641free(lattice_orbit_length);642free(smallest);643}644else{645/* for this affine class, there are only subgroups from one lattice */646if (gitter_no[k][0] == 1){647printf("%i: ", k + 1 + data->first_aff[i]);648for (l = 0; l < data->aff_no[j]; l++){649if (zwischenerg[gitter_no[k][1]].x[k][l] > 0){650for (q = 0; q < zwischenerg[gitter_no[k][1]].x[k][l]; q++){651printf("%i (%i, ", l + 1 + data->first_aff[j],652zwischenerg[gitter_no[k][1]].l[k][l][q + 1] *653kernel_factor[gitter_no[k][1]]);654if (oflag)655printf("%i, ", zwischenerg[gitter_no[k][1]].o[k][l][q + 1]);656printf("%i^%i) ", primes[gitter_no[k][1]], exponent[gitter_no[k][1]]);657erg->array.SZ[k + data->first_aff[i]][l + data->first_aff[j]]++;658}659}660}661printf("\n");662}663}664}665if (entry.anz == 1){666/* there is only one lattice */667for (k = 0; k < data->aff_no[i]; k++){668if (gitter_no[k][0] != 0){669printf("%i: ", k + 1 + data->first_aff[i]);670for (l = 0; l < data->aff_no[j]; l++){671if (zwischenerg[0].x[k][l] > 0){672for (q = 0; q < zwischenerg[0].x[k][l]; q++){673printf("%i (%i, ", l + 1 + data->first_aff[j],674zwischenerg[0].l[k][l][q + 1] *675kernel_factor[0]);676if (oflag)677printf("%i, ", zwischenerg[0].o[k][l][q + 1]);678printf("%i^%i) ", primes[0], exponent[0]);679erg->array.SZ[k + data->first_aff[i]][l + data->first_aff[j]]++;680}681}682}683printf("\n");684}685}686}687free_SOL_TYP(zwischenerg, entry.anz, data->aff_no[i], data->aff_no[j]);688for (k = 0 ; k < data->aff_no[i]; k++){689free(gitter_no[k]);690}691free(gitter_no);692free(kernel_factor);693free(exponent);694free(primes);695}696for (j = 0; j < translanz; j++){697free_mat(translationen[j]);698}699free(translationen);700}701702/* clean up */703for (i = 0; i < data->pres->rows; i++)704wordfree(relator + i);705free(relator);706free_mat(id);707for (i = 0; i < data->Z_no; i++){708for (j = 0; j < data->Z[i]->normal_no; j++){709if (dataNinv[i][j] != NULL)710free_mat(dataNinv[i][j]);711}712free(dataNinv[i]);713}714free(dataNinv);715716return(erg);717}718719720721722723724