stoufferlab / pymfinder

A Python package with which to find network motifs in complex networks and to analyze a growing list of network-motif related stuff.
MIT License
16 stars 7 forks source link

`single_connected_component` in `wrapper.c` might need minor modifications on windows using MSVC #37

Open immorBen opened 5 months ago

immorBen commented 5 months ago

basic info:

runing pyhton setup.py install raised below errors:

pymfinder/mfinder/wrapper.c(455): error C2057: expected constant expression 
pymfinder/mfinder/wrapper.c(455): error C2466: cannot allocate an array of constant size 0
pymfinder/mfinder/wrapper.c(455): error C2133: 'cc': unknown size
pymfinder/mfinder/wrapper.c(456): error C2057: expected constant expression                                                                                       
pymfinder/mfinder/wrapper.c(456): error C2466: cannot allocate an array of constant size 0                                                                        
pymfinder/mfinder/wrapper.c(456): error C2133: 'checked': unknown size                                                                                            
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\x86_amd64\\cl.exe' failed with exit code 2   

chatgpt provided a solution that the below should be used (dynamically memory allocation):

int single_connected_component(int64 id, int mtf_sz) {
    int i, j, k;
    int added;

    Matrix *M;
    M = init_matrix(mtf_sz);
    fill_mat_id(M, id);

    // Allocate memory dynamically
    int *cc = (int *)malloc((mtf_sz + 1) * sizeof(int));
    int *checked = (int *)malloc((mtf_sz + 1) * sizeof(int));

    if (cc == NULL || checked == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        free(cc);
        free(checked);
        free_matrix(M);
        free(M);
        return FALSE;
    }

    for(i = 1; i <= mtf_sz; i++) {
        cc[i] = FALSE;
        checked[i] = FALSE;
    }

    cc[1] = TRUE;

    added = TRUE;
    while(added == TRUE) {
        added = FALSE;
        for(i = 1; i <= mtf_sz; i++) {
            if(cc[i] == TRUE && checked[i] == FALSE) {
                checked[i] = TRUE;
                for(j = 1; j <= mtf_sz; j++) {
                    if(MTRX(M, i, j) == 1 || MTRX(M, j, i) == 1) {
                        if(cc[j] == FALSE) {
                            cc[j] = TRUE;
                            added = TRUE;
                        }
                    }
                }
            }
        }
    }

    free(cc);
    free(checked);
    free_matrix(M);
    free(M);

    for(i = 1; i <= mtf_sz; ++i)
        if(cc[i] == FALSE)
            return FALSE;

    return TRUE;
}

it works for me (although still with some warnings, but...i'm a newbie, have no idea), test passed:

Ran 10 tests in 2.036s

OK

follow-up QAs: Q: but this works without the above error on wsl, do different os treat the code of this function differently? chatgpt:

Yes, different operating systems and compilers can treat code differently, especially when it comes to variable length arrays (VLAs). VLAs are part of the C99 standard and supported by GCC and Clang, but not by older versions of the Microsoft Visual C++ (MSVC) compiler. In your case, the error occurs because MSVC does not support VLAs. On WSL (Windows Subsystem for Linux), GCC or Clang, which do support VLAs, are typically used, allowing the code to compile and run without issues. To ensure compatibility across different compilers and platforms, it is best to avoid VLAs and use dynamic memory allocation instead, as demonstrated in the previous response. This approach makes your code more portable and ensures it works consistently on different systems and compilers.