proposed acb_set_str() function

8 views
Skip to first unread message

American Citizen

unread,
Nov 9, 2025, 6:26:50 PM (4 days ago) Nov 9
to flint-devel
I am submitting a function to the acb library called acb_set_str() since I encountered problems trying to input very high precision complex numbers.

The function signature is

int acb_set_str(acb_t res, const char * inp, slong prec);

The program is listed below: (remove main() which was used for testing)

The input can be one flint number in which case the imag value is set to zero. If two flint numbers are input, then a true complex number is obtained. The flint numbers can be bracked with their radius, i.e. [3.14159264 +/- 1e-14] as valid input. To enter a pure imaginary value, simply set the real part to 0. The main test program used quotes to delineate the string for input.

/*
    Copyright (C) 2025 Randall L. Rathbun

    This file is intended to become part of FLINT.

    FLINT is free software: you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License (LGPL) as published
    by the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.  See <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#include "flint/acb.h"

int acb_set_str(acb_t res, const char * inp, slong prec)
{
    // test input
    // printf("inp = %s\n",inp);

    char * buf;
    char * split;
    const int max_tokens = 6;
    char * tokens[max_tokens];
    int num_toks = 0;
   
    buf = flint_malloc(strlen(inp) + 1);
    strcpy(buf, inp);

    // Tokenize input string (by spaces)
    split = strtok(buf, " ");
    while (split != NULL && num_toks < max_tokens) {
        tokens[num_toks++] = split;
        split = strtok(NULL, " ");
    }

    // test tokens
/*
    printf("num_toks: %d\n",num_toks);
    for ( int ix=0; ix<num_toks; ix++) {
        printf("token[%d] = %s\n",ix,tokens[ix]);
    }
*/

    // Handle different cases based on the number of tokens
    int error = 0;
    switch (num_toks) {
        case 1:
            // Single token
            error = arb_set_str(acb_realref(res), tokens[0], prec);
            if (error) { break; }
            arb_zero(acb_imagref(res));  // Set imaginary part to zero
            break;

        case 2:
            // Two tokens
            error = arb_set_str(acb_realref(res), tokens[0], prec);
            if (error) { break; } else {
                error = arb_set_str(acb_imagref(res), tokens[1], prec);
            }
            break;

        case 3:
            // Three tokens (one real number with no imaginary part)
            if (strcmp(tokens[1], "+/-") == 0) {
                // this is strictly a real number +/- variance
                char * tmp = flint_malloc(strlen(inp) + 1);
                memset(tmp, '\0', sizeof(tmp));
                strcat(tmp,tokens[0]); strcat(tmp," "); strcat (tmp,tokens[1]); strcat(tmp," "); strcat(tmp,tokens[2]);
                // printf("tmp = %s\n",tmp);
                // Set real part
                error = arb_set_str(acb_realref(res), tmp, prec);
                if (error) { flint_free(tmp); break; }
                // set imag to zero
                arb_zero(acb_imagref(res));  // Set imaginary part to zero
                flint_free(tmp);
            }
            break;

        case 4:
            // Four tokens (one real number with variance and pure imaginary number)
            if (strcmp(tokens[1], "+/-") == 0) {
                // this is strictly a real number +/- variance
                char * tmp = flint_malloc(strlen(inp) + 1);
                memset(tmp, '\0', sizeof(tmp));
                strcat(tmp,tokens[0]); strcat(tmp," "); strcat (tmp,tokens[1]); strcat(tmp," "); strcat(tmp,tokens[2]);
                // printf("tmp = %s\n",tmp);
                // Set real part
                error = arb_set_str(acb_realref(res), tmp, prec);
                if (error) { flint_free(tmp); break; }

                // set imag to zero
                arb_zero(acb_imagref(res));  // Set imaginary part to zero
                error = arb_set_str(acb_imagref(res), tokens[3], prec);
                if (error) { flint_free(tmp); break; }
                flint_free(tmp);
            }
            break;

        case 6:
            // six tokens; must have two "+/-"
            if (strcmp(tokens[1], "+/-") == 0 && strcmp(tokens[4], "+/-") == 0) {
                char * tmp = flint_malloc(strlen(inp) + 1);
                memset(tmp, '\0', sizeof(tmp));
                strcat(tmp,tokens[0]); strcat(tmp," "); strcat(tmp,tokens[1]); strcat(tmp," "); strcat(tmp,tokens[2]);
                // Set real part
                error = arb_set_str(acb_realref(res), tmp, prec);
                if (error) { flint_free(tmp); break; }
                // test real part
/*
                printf("real: ");
                arb_printd(acb_realref(res), 10); // Print real part
                printf("\n");
*/
                // Set imaginary part
                memset(tmp, '\0', sizeof(tmp));
                strcat(tmp,tokens[3]); strcat(tmp," "); strcat(tmp,tokens[4]); strcat(tmp," "); strcat(tmp,tokens[5]);
                error = arb_set_str(acb_imagref(res), tmp, prec);
/*
                printf("imag: ");
                arb_printd(acb_imagref(res), 10); // Print imag part
                printf("\n");
*/
                if (error) { flint_free(tmp); break; }
                flint_free(tmp);
            }
            break;

        default:
            // Handle error for unsupported formats
            error = 1;  // Set appropriate error code
    }

    flint_free(buf);
    return error;
}

int main(int argc, char *argv[])
{
    if (argc < 2) {
        fprintf(stderr, "Usage: %s <input_string>\n", argv[0]);
        return 1;
    }

    arb_t real;
    arb_init(real);

    acb_t result;
    acb_init(result);
    slong precision = 50; // Example precision

    int error = acb_set_str(result, argv[1], precision);
    if (error) {
        fprintf(stderr, "Error setting complex number from string.\n");
    } else {
        printf("Complex number: [");
        arb_printd(acb_realref(result), 10); // Print real part
        printf("] + [");
        arb_printd(acb_imagref(result), 10); // Print imaginary part
        printf("]*i\n");
    }

    arb_clear(real);
    acb_clear(result);
    return 0;
}




Aasim

unread,
Nov 9, 2025, 11:13:16 PM (4 days ago) Nov 9
to flint...@googlegroups.com
I think it's assumed here that the user of this method will not mess up 
the input string(like assuming inp will not be NULL or will not have 
arbitrary substrings either) and hence the implementation is flexible 
with error handling at some points. That's fine I hope. 

One thing though:


char * tmp = flint_malloc(strlen(inp) + 1);
memset(tmp, '\0', sizeof(tmp));  

The above lines are used a few times here. 
sizeof(tmp) will return the size of this pointer (8 bytes typically on 64-bit systems),
but here, potentially more memory is being allocated i.e. strlen(inp) + 1 bytes long.
So I guess if I'm not mistaken then this only zeros out the first 8 bytes and the rest 
is probably left uninitialized(garbage). 

Since you're using strcat() immediately after this, it's only gonna be looking for "\0"
, we might only need to set the first byte like:

tmp[0] = '\0';  // set first char to null terminator

memset calls themselves can just be reduced/consolidated here since 
they might not be necessary after the first call since tmp is already being 
zeroed out. 

--

---
You received this message because you are subscribed to the Google Groups "flint-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flint-devel...@googlegroups.com.
To view this discussion, visit https://groups.google.com/d/msgid/flint-devel/c4273be8-0bb6-46c4-a3ef-91872831b724n%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages