The MASM Forum

64 bit assembler => UASM Assembler Development => Topic started by: six_L on May 09, 2025, 11:06:09 PM

Title: Riemann Zeta Function
Post by: six_L on May 09, 2025, 11:06:09 PM
Hi,all
Zeta(z)=1/1^z+1/2^z+1/3^z+...+1/n^z+...
n: All natural numbers
z = a+bi, a != 1
Zeta(z) trivial zeros: a = -2,-4,-6,...,-2n
Zeta(z) Nontrivial zeros: a = 1/2, b = ?(40%) [There isn't still strict proof now]
The Zeta(z) Nontrivial zeros are related to the count of prime numbers.

I drawed the Zeta(z) curve. but it is strange. Do you know how to draw the following left image?
Title: Re: Riemann Zeta Function
Post by: zedd on May 10, 2025, 12:09:20 AM
I havent a clue, but it looks very similar in some aspects to a cardioid polar pattern (https://www.lewitt-audio.com/blog/cardioid-polar-pattern), at least the outermost curves.. except for the orientation.

(https://i.postimg.cc/fWS6vmwY/polar-pattern-03-transp-0.png)

Probably doesn't help you at all, but it was the first thing that came to mind when I saw your image on the left.


Title: Re: Riemann Zeta Function
Post by: guga on May 10, 2025, 12:58:18 AM
Try this (press R to reset animation). You can also save the generated image

Links below holds the full source (and solution database for VS2022)
https://www.mediafire.com/file/t4bxo1lgvc2bdm8/Zeta10.rar/file (https://www.mediafire.com/file/t4bxo1lgvc2bdm8/Zeta10.rar/file)
https://www.mediafire.com/file/2axp5fyma44y6on/Zeta11.zip/file (https://www.mediafire.com/file/2axp5fyma44y6on/Zeta11.zip/file)


(https://i.postimg.cc/xN3t1HHw/Clipboard-05-09-2025-01.png) (https://postimg.cc/xN3t1HHw)

// ZetaVisualizerFinal.c - Extended coordinate labels to match grid lines
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
#include <commdlg.h>

#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")

using namespace Gdiplus;

// Global variables for animation
static float animationProgress = 0.0f; // 0.0 to 1.0
static const float ANIMATION_SPEED = 0.005f; // Adjust for faster/slower animation
static const UINT_PTR ANIMATION_TIMER_ID = 1;
static bool isAnimationRunning = false; // Track animation state

// Complex number structure
typedef struct {
    double real;
    double imag;
} Complex;

// Improved Zeta function with better convergence
Complex Zeta(Complex s, int iterations) {
    Complex result = { 0.0, 0.0 };
    double running_sum = 0.0;

    // Standard Dirichlet series for first N terms
    for (int n = 1; n <= iterations; n++) {
        double term = 1.0 / pow(n, s.real);
        double angle = -s.imag * log(n);
        result.real += term * cos(angle);
        result.imag += term * sin(angle);

        if (n > 10 && fabs(result.real - running_sum) < 1e-10) {
            break;
        }
        running_sum = result.real;
    }

    // Add a simple Euler-Maclaurin correction for remainder
    if (iterations > 10) {
        int N = iterations;
        double term = 1.0 / pow(N + 1, s.real);
        double angle = -s.imag * log(N + 1);
        // Approximate remainder: integral term ~ 1/(s-1) * N^(1-s)
        double correction_real = term * cos(angle) / (s.real - 1.0);
        double correction_imag = term * sin(angle) / (s.real - 1.0);
        result.real += correction_real;
        result.imag += correction_imag;
    }

    return result;
}

// Draw the enhanced Zeta function visualization
void DrawEnhancedZeta(HDC hdc, int width, int height, float progress) {
    Graphics graphics(hdc);
    graphics.SetSmoothingMode(SmoothingModeAntiAlias);
    graphics.SetCompositingQuality(CompositingQualityHighQuality);
    graphics.SetTextRenderingHint(TextRenderingHintAntiAlias); // Improve text rendering

    // Dark gradient background
    LinearGradientBrush background(
        Point(0, 0),
        Point(width, height),
        Color(255, 10, 20, 50), // Deep blue
        Color(255, 0, 0, 0));  // Black
    graphics.FillRectangle(&background, 0, 0, width, height);

    // Set up coordinate system
    REAL centerX = width / 2.0f;
    REAL centerY = height / 2.0f;
    REAL scale = (REAL)min(width, height) / 4.0f;
    REAL unitScale = scale / 6.0f; // Pixels per unit (zeta.real or zeta.imag)

    // Draw subtle grid lines
    Pen gridPen(Color(50, 100, 100, 150), 0.3f);
    for (int i = -6; i <= 6; i++) {
        graphics.DrawLine(&gridPen,
            0.0f, centerY + i * scale / 3.0f,
            (REAL)width, centerY + i * scale / 3.0f);
        graphics.DrawLine(&gridPen,
            centerX + i * scale / 3.0f, 0.0f,
            centerX + i * scale / 3.0f, (REAL)height);
    }

    // Draw glowing axes
    LinearGradientBrush axisBrush(
        Point(0, (int)centerY),
        Point(width, (int)centerY),
        Color(150, 200, 200, 255),
        Color(50, 100, 100, 100));
    Pen axisPen(&axisBrush, 1.8f);
    graphics.DrawLine(&axisPen, 0.0f, centerY, (REAL)width, centerY);
    graphics.DrawLine(&axisPen, centerX, 0.0f, centerX, (REAL)height);

    // Draw critical line
    LinearGradientBrush criticalBrush(
        Point((int)centerX, 0),
        Point((int)centerX, height),
        Color(150, 255, 150, 50),
        Color(50, 100, 255, 50));
    Pen criticalPen(&criticalBrush, 2.0f);
    REAL criticalX = centerX + scale * 0.5f;
    graphics.DrawLine(&criticalPen, criticalX, 0.0f, criticalX, (REAL)height);

    // Draw Zeta function curve with animation
    const int iterations = 200;
    const double t_start = 0.0;
    const double t_end = 30.0;
    const double t_step = 0.02;
    double t_max = t_start + progress * (t_end - t_start); // Animate up to t_max

    GraphicsPath path;
    PointF prevPoint;
    bool firstPoint = true;

    for (double t = t_start; t <= t_max; t += t_step) {
        Complex s = { 0.5, t };
        Complex zeta = Zeta(s, iterations);

        REAL x = centerX + (REAL)zeta.imag * scale / 6.0f;
        REAL y = centerY - (REAL)zeta.real * scale / 6.0f;

        if (!firstPoint) {
            path.AddLine(prevPoint, PointF(x, y));
        }
        else {
            path.StartFigure();
            firstPoint = false;
        }
        prevPoint = PointF(x, y);
    }

    // Neon gradient for Zeta curve
    Color colors[] = {
        Color(200, 255, 50, 50),
        Color(200, 255, 165, 0),
        Color(200, 255, 0, 255),
        Color(200, 50, 50, 255)
    };
    REAL positions[] = { 0.0f, 0.33f, 0.67f, 1.0f };
    LinearGradientBrush pathBrush(
        Point(0, (int)(centerY - scale)),
        Point(0, (int)(centerY + scale)),
        Color(255, 255, 255, 255),
        Color(255, 255, 255, 255));
    pathBrush.SetInterpolationColors(colors, positions, 4);

    // Draw glow and main curve
    Pen glowPen(&pathBrush, 5.0f);
    glowPen.SetColor(Color(100, 255, 255, 255));
    graphics.DrawPath(&glowPen, &path);
    Pen zetaPen(&pathBrush, 2.5f);
    graphics.DrawPath(&zetaPen, &path);

    // Add annotations with adjusted positions
    Font font(L"Cambria Math", 16, FontStyleBold);
    Font smallFont(L"Cambria Math", 12, FontStyleRegular); // Smaller font for coordinate labels
    SolidBrush shadowBrush(Color(80, 0, 0, 0));
    SolidBrush textBrush(Color(255, 230, 230, 230));
    StringFormat format;
    format.SetAlignment(StringAlignmentCenter);

    // Title: "ζ(s) where s = ½ + ti" (top center)
    Font bigFont(L"Cambria Math", 20, FontStyleBold);
    graphics.DrawString(L"ζ(s) where s = ½ + ti", -1, &bigFont,
        PointF(centerX + 4.0f, 24.0f), &format, &shadowBrush);
    graphics.DrawString(L"ζ(s) where s = ½ + ti", -1, &bigFont,
        PointF(centerX, 20.0f), &format, &textBrush);

    // Critical line label: "Re(s) = ½" (right side, near critical line)
    graphics.DrawString(L"Re(s) = ½", -1, &font,
        PointF(criticalX + 4.0f, 60.0f), &format, &shadowBrush);
    graphics.DrawString(L"Re(s) = ½", -1, &font,
        PointF(criticalX, 56.0f), &format, &textBrush);

    // Axis label: "Im(ζ(s))" (right side)
    REAL imLabelX = (REAL)width - 100.0f;
    graphics.DrawString(L"Im(ζ(s))", -1, &font,
        PointF(imLabelX + 4.0f, centerY - 24.0f), &shadowBrush);
    graphics.DrawString(L"Im(ζ(s))", -1, &font,
        PointF(imLabelX, centerY - 20.0f), &textBrush);

    // Axis label: "Re(ζ(s))" (bottom center)
    graphics.DrawString(L"Re(ζ(s))", -1, &font,
        PointF(centerX + 14.0f, (REAL)height - 44.0f), &shadowBrush);
    graphics.DrawString(L"Re(ζ(s))", -1, &font,
        PointF(centerX + 10.0f, (REAL)height - 40.0f), &textBrush);

    // Add coordinate labels for horizontal axis (Im(ζ(s))): -12 to 12, step 2
    for (int i = -6; i <= 6; i++) {
        int value = i * 2; // Grid lines are at intervals of 2 units
        REAL xPos = centerX + value * unitScale;
        WCHAR label[16];
        swprintf(label, 16, L"%d", value);
        graphics.DrawString(label, -1, &smallFont,
            PointF(xPos + 2.0f, centerY + 16.0f), &format, &shadowBrush);
        graphics.DrawString(label, -1, &smallFont,
            PointF(xPos, centerY + 12.0f), &format, &textBrush);
    }

    // Add coordinate labels for vertical axis (Re(ζ(s))): -12 to 12, step 2
    StringFormat nearFormat;
    nearFormat.SetAlignment(StringAlignmentNear); // Left-align for vertical labels
    for (int i = -6; i <= 6; i++) {
        int value = i * 2; // Grid lines are at intervals of 2 units
        REAL yPos = centerY - value * unitScale; // Negative because screen y increases downward
        WCHAR label[16];
        if (value == 0) {
            swprintf(label, 16, L"0");
        }
        else {
            swprintf(label, 16, L"%di", value);
        }
        graphics.DrawString(label, -1, &smallFont,
            PointF(centerX - 30.0f + 2.0f, yPos + 2.0f), &nearFormat, &shadowBrush);
        graphics.DrawString(label, -1, &smallFont,
            PointF(centerX - 30.0f, yPos), &nearFormat, &textBrush);
    }

    // Add animated non-trivial zero markers
    double zeros[] = { 14.1347, 21.0220, 25.0109, 30.4249 }; // Known zeros
    int numZeros = sizeof(zeros) / sizeof(zeros[0]);
    for (int i = 0; i < numZeros; i++) {
        if (zeros[i] <= t_max) { // Only draw zeros up to current progress
            Complex s = { 0.5, zeros[i] };
            Complex zeta = Zeta(s, iterations);
            REAL x = centerX + (REAL)zeta.imag * scale / 6.0f;
            REAL y = centerY - (REAL)zeta.real * scale / 6.0f;

            LinearGradientBrush zeroBrush(
                Point((int)(x - 10.0f), (int)(y - 10.0f)),
                Point((int)(x + 10.0f), (int)(y + 10.0f)),
                Color(200, 255, 100, 100),
                Color(0, 255, 255, 255));
            graphics.FillEllipse(&zeroBrush, x - 7.0f, y - 7.0f, 14.0f, 14.0f);

            Pen zeroPen(Color(150, 255, 255, 255), 1.0f);
            graphics.DrawEllipse(&zeroPen, x - 7.0f, y - 7.0f, 14.0f, 14.0f);
        }
    }
}

// Helper function to get PNG encoder CLSID
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) {
    UINT num = 0, size = 0;
    Gdiplus::GetImageEncodersSize(&num, &size);
    if (size == 0) return -1;

    ImageCodecInfo* pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
    Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);

    for (UINT j = 0; j < num; ++j) {
        if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
            *pClsid = pImageCodecInfo[j].Clsid;
            free(pImageCodecInfo);
            return j;
        }
    }

    free(pImageCodecInfo);
    return -1;
}

// Save visualization as PNG
void SaveAsPng(HWND hWnd, int width, int height, const WCHAR* filename) {
    // Create a bitmap
    Bitmap bitmap(width, height, PixelFormat32bppARGB);
    Graphics bitmapGraphics(&bitmap);
    bitmapGraphics.SetSmoothingMode(SmoothingModeAntiAlias);
    bitmapGraphics.SetCompositingQuality(CompositingQualityHighQuality);
    bitmapGraphics.SetTextRenderingHint(TextRenderingHintAntiAlias);

    // Draw the full visualization (progress = 1.0)
    HDC hdc = bitmapGraphics.GetHDC();
    DrawEnhancedZeta(hdc, width, height, 1.0f);
    bitmapGraphics.ReleaseHDC(hdc);

    // Save as PNG
    CLSID clsid;
    if (GetEncoderClsid(L"image/png", &clsid) != -1) {
        bitmap.Save(filename, &clsid, NULL);
        char msg[512];
        snprintf(msg, sizeof(msg), "Visualization saved as %S", filename);
        MessageBoxA(hWnd, msg, "Success", MB_OK | MB_ICONINFORMATION);
    }
    else {
        MessageBoxA(hWnd, "Failed to save PNG: PNG encoder not found", "Error", MB_OK | MB_ICONERROR);
    }
}

// Open file dialog for saving PNG
void ShowSaveDialog(HWND hWnd, int width, int height) {
    WCHAR filename[MAX_PATH] = L"ZetaVisualization.png";
    OPENFILENAMEW ofn = { 0 };
    ofn.lStructSize = sizeof(OPENFILENAMEW);
    ofn.hwndOwner = hWnd;
    ofn.lpstrFilter = L"PNG Files (*.png)\0*.png\0All Files (*.*)\0*.*\0";
    ofn.lpstrFile = filename;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrDefExt = L"png";
    ofn.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;

    if (GetSaveFileNameW(&ofn)) {
        SaveAsPng(hWnd, width, height, filename);
    }
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    static int width, height;

    switch (message) {
    case WM_CREATE:
        // Animation starts paused; no timer set initially
        break;

    case WM_TIMER:
        if (wParam == ANIMATION_TIMER_ID) {
            animationProgress += ANIMATION_SPEED;
            if (animationProgress > 1.0f) {
                animationProgress = 1.0f; // Stop at full progress
                KillTimer(hWnd, ANIMATION_TIMER_ID);
                isAnimationRunning = false;
            }
            InvalidateRect(hWnd, NULL, FALSE); // FALSE to avoid background erase
        }
        break;

    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);

        RECT rect;
        GetClientRect(hWnd, &rect);
        width = rect.right;
        height = rect.bottom;

        // Create double buffer
        HDC memDC = CreateCompatibleDC(hdc);
        HBITMAP memBitmap = CreateCompatibleBitmap(hdc, width, height);
        HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap);

        // Fill background to avoid artifacts
        HBRUSH blackBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
        FillRect(memDC, &rect, blackBrush);

        // Draw to memory DC
        DrawEnhancedZeta(memDC, width, height, animationProgress);

        // Copy to screen
        BitBlt(hdc, 0, 0, width, height, memDC, 0, 0, SRCCOPY);

        // Clean up
        SelectObject(memDC, oldBitmap);
        DeleteObject(memBitmap);
        DeleteDC(memDC);

        EndPaint(hWnd, &ps);
        break;
    }
    case WM_SIZE:
        width = LOWORD(lParam);
        height = HIWORD(lParam);
        InvalidateRect(hWnd, NULL, TRUE);
        break;

    case WM_COMMAND:
        switch (LOWORD(wParam)) {
        case 1001: // Save As
            ShowSaveDialog(hWnd, width, height);
            break;
        case 1002: // Start Animation
            if (!isAnimationRunning) {
                SetTimer(hWnd, ANIMATION_TIMER_ID, 16, NULL); // ~60 FPS
                isAnimationRunning = true;
            }
            break;
        case 1003: // Pause Animation
            if (isAnimationRunning) {
                KillTimer(hWnd, ANIMATION_TIMER_ID);
                isAnimationRunning = false;
            }
            break;
        }
        break;

    case WM_KEYDOWN:
        if (wParam == 'R') { // Reset animation
            animationProgress = 0.0f;
            if (!isAnimationRunning) {
                SetTimer(hWnd, ANIMATION_TIMER_ID, 16, NULL);
                isAnimationRunning = true;
            }
            InvalidateRect(hWnd, NULL, FALSE);
        }
        break;

    case WM_DESTROY:
        if (isAnimationRunning) {
            KillTimer(hWnd, ANIMATION_TIMER_ID);
        }
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProcA(hWnd, message, wParam, lParam);
    }
    return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    // Create menu
    HMENU hMenu = CreateMenu();
    HMENU hFileMenu = CreatePopupMenu();
    AppendMenuA(hFileMenu, MF_STRING, 1001, "Save As...");
    AppendMenuA(hFileMenu, MF_STRING, 1002, "Start Animation");
    AppendMenuA(hFileMenu, MF_STRING, 1003, "Pause Animation");
    AppendMenuA(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, "File");

    WNDCLASSA wc = { 0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = "ZetaVisualizer";
    wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    RegisterClassA(&wc);

    HWND hWnd = CreateWindowA("ZetaVisualizer", "Riemann Zeta Function Visualizer",
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        1200, 900, NULL, hMenu, hInstance, NULL);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    MSG msg;
    while (GetMessageA(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessageA(&msg);
    }

    DestroyMenu(hMenu);
    GdiplusShutdown(gdiplusToken);
    return (int)msg.wParam;
}

Attached the binary file. And on the links, the full source
Title: Re: Riemann Zeta Function
Post by: jack on May 10, 2025, 01:27:48 AM
hi guga
I did a zeta approximation in FreeBasic years ago using the following
    '  f(k)=(k+nc)^-n

    '  inf          nc              inf                        inf
    '  ====          ====          /                          ==== B
    '  \      1    \      1      [                          \    (2*k)  (2*k-1)
    '  >    ----- =  >    ----- +  I    f(k) dk + B * f(0) -  >  ------ f  (0)
    '  /      n      /      n      ]              1          /    (2*k)!
    '  ====  k      ====  k      /                          ====
    '  k = 1        k = 1          0                          k = 1
I posted the code here https://www.freebasic.net/forum/viewtopic.php?p=193860#p193860 (https://www.freebasic.net/forum/viewtopic.php?p=193860#p193860)
Title: Re: Riemann Zeta Function
Post by: guga on May 10, 2025, 01:31:50 AM
Quote from: jack on May 10, 2025, 01:27:48 AMhi guga
I did a zeta approximation in FreeBasic years ago using the following
    '  f(k)=(k+nc)^-n

    '  inf           nc              inf                        inf
    '  ====          ====           /                          ==== B
    '  \       1     \       1      [                          \    (2*k)   (2*k-1)
    '   >    ----- =  >    ----- +  I    f(k) dk + B * f(0) -   >   ------ f  (0)
    '  /      n      /      n       ]               1          /    (2*k)!
    '  ====  k       ====  k       /                           ====
    '  k = 1         k = 1          0                          k = 1
I can post the code if anyone is interested

Tks, Jack. It would be good to see the code. Maybe it can later be ported to masm or even plain C if needed
Title: Re: Riemann Zeta Function
Post by: jack on May 10, 2025, 01:36:15 AM
I edited my post with a link to the source
Title: Re: Riemann Zeta Function
Post by: guga on May 10, 2025, 01:43:20 AM
Quote from: jack on May 10, 2025, 01:36:15 AMI edited my post with a link to the source

Tks, try this. Grok ported your version.

https://www.mediafire.com/file/bpmn4b5pj74ka2m/Zeta12.rar/file (https://www.mediafire.com/file/bpmn4b5pj74ka2m/Zeta12.rar/file)

(https://i.postimg.cc/hfYzXH5P/Clipboard-05-09-2025-01.png) (https://postimg.cc/hfYzXH5P)
Title: Re: Riemann Zeta Function
Post by: jack on May 10, 2025, 07:39:56 AM
hey guga
Grok explained what the code does better than my comments in my code  :biggrin:
Title: Re: Riemann Zeta Function
Post by: guga on May 10, 2025, 08:49:36 AM
Quote from: jack on May 10, 2025, 07:39:56 AMhey guga
Grok explained what the code does better than my comments in my code  :biggrin:
Indeed :biggrin: Grok  is a wonderful tool. I started 1st using deepseek to create some basic app that worked similar to the left image that  six_L  showed. But, the result was inaccurate. Nevertheless, i took the code generated on deepseek and used it through Grok (the x version and not the one from the site) to it fix the code and make it more similar to the image, enhancing graphics and focusing in using gdi+. It fixed and i started to play with it, adding animation, a menu etc. Then when you uploaded your freebasic version, since i already had the skeleton, i mainly asked Grok to adapt the code he just did in C to yours in freebasic.

Grok does a very good work in Plain C language, but still lack the same skill in what concerns assembly (no matter if for masm, rosasm, fasm or nasm). For assembly programming you must not trust 100% on the generated code, but use it mainly as a guidance to improve yours.

In any case, the results i´ve seen so far are good enough to save some time in development. Most likely, until the end of the year i believe Grok (and others) should be more advanced in what is related to assembly language to save us even more time for coding.

One thing interesting, i have no idea what is this zeta all about. I only realized what was that, after pasting the comments  six_L  did on deepseek and ask him to do an app based on this. The rest, was fine tunned with Grok.

I started on deepseek, simply inserting this:

QuotePls create me a function in plain C using Gdi+ on a way i can generate the graphic on this link (image on left)https://masm32.com/board/index.php?action=dlattach;attach=18375;image. The goal is: Hi,all
Zeta(z)=1/1^z+1/2^z+1/3^z+...+1/n^z+...
n: All natural numbers
z = a+bi, a != 1
Zeta(z) trivial zeros: a = -2,-4,-6,...,-2n
Zeta(z) Nontrivial zeros: a = 1/2, b = ?(40%) [There isn't still strict proof now]
The Zeta(z) Nontrivial zeros are related to the count of prime numbers.

I drawed the Zeta(z) curve. but it is strange. Do you know how to draw the following left image?

And that was all it was needed to it create a zeta visualizer in C. Then, as i said, i used the generated code in x for fine tune and fix it.
Title: Re: Riemann Zeta Function
Post by: six_L on May 10, 2025, 11:22:29 PM
Hi,zedd/guga/jack
Thanks your help.
Quite useful information.
I am very interested in your Zeta algorithms. I need to learn hardly.

Zeta(z)=1/1^z+1/2^z+1/3^z+...+1/n^z+...
=1/(1-1/2^z) * 1/(1-1/3^z) * 1/(1-1/5^z) * 1/(1-1/7^z) * 1/(1-1/11^z) * ... * 1/(1-1/p^z)   
n: All natural numbers
z = a+bi, a != 1
p = All prime numbers

ln(Zeta(z)) = -[ln(1-1/2^z)+ln(1-1/3^z)+ln(1-1/5^z)+ln(1-1/7^z)+...+ln(1-1/p^z)]
                 = x
Zeta(z) = e^x

150 years ago, no computer, the great mathematicians used their pens to calculate the Zeta(z) Nontrivial zeros. That's a very difficult job. Admiring!

The problem with the previous images was due to the step value being too large.
now it works fine.
Title: Re: Riemann Zeta Function
Post by: guga on May 11, 2025, 12:51:03 AM
Hi Six_L you´re welcome.

Now, try this. (Added zoom with mouse wheel and pg up/down), also it starts (resets) with a space and not only the R key

// ZetaVisualizerFinal.c - Added Page Up/Page Down zoom, smoothed curve, fixed starting line
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <objidl.h>
#include <gdiplus.h>
#include <math.h>
#include <stdio.h>
#include <time.h>
#include <commdlg.h>
#include <vector>

#pragma comment(lib, "gdiplus.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")

using namespace Gdiplus;

// Global variables for animation and zoom
static float animationProgress = 0.0f; // 0.0 to 1.0
static const float ANIMATION_SPEED = 0.005f; // Adjust for faster/slower animation
static const UINT_PTR ANIMATION_TIMER_ID = 1;
static bool isAnimationRunning = false; // Track animation state
static float zoomFactor = 1.0f; // Zoom factor (1.0 = default, >1 zoom in, <1 zoom out)

// Complex number structure
typedef struct {
    double real;
    double imag;
} Complex;

// Complex arithmetic functions
Complex ComplexAdd(Complex a, Complex b) {
    Complex result;
    result.real = a.real + b.real;
    result.imag = a.imag + b.imag;
    return result;
}

Complex ComplexMul(Complex a, Complex b) {
    Complex result;
    result.real = a.real * b.real - a.imag * b.imag;
    result.imag = a.real * b.imag + a.imag * b.real;
    return result;
}

Complex ComplexSub(Complex a, Complex b) {
    Complex result;
    result.real = a.real - b.real;
    result.imag = a.imag - b.imag;
    return result;
}

Complex ComplexPowReal(Complex base, double exponent) {
    double r = sqrt(base.real * base.real + base.imag * base.imag);
    double theta = atan2(base.imag, base.real);
    double ln_r = log(r);
    double exponent_ln_r = exponent * ln_r;
    double exponent_theta = exponent * theta;
    Complex result;
    result.real = exp(exponent_ln_r) * cos(exponent_theta);
    result.imag = exp(exponent_ln_r) * sin(exponent_theta);
    return result;
}

Complex ComplexPow(Complex base, Complex exponent) {
    double r = sqrt(base.real * base.real + base.imag * base.imag);
    double theta = atan2(base.imag, base.real);
    Complex ln_base;
    ln_base.real = log(r);
    ln_base.imag = theta;
    Complex exponent_ln_base = ComplexMul(exponent, ln_base);
    double magnitude = exp(exponent_ln_base.real);
    Complex result;
    result.real = magnitude * cos(exponent_ln_base.imag);
    result.imag = magnitude * sin(exponent_ln_base.imag);
    return result;
}

Complex ComplexDiv(Complex a, Complex b) {
    double denom = b.real * b.real + b.imag * b.imag;
    Complex result;
    result.real = (a.real * b.real + a.imag * b.imag) / denom;
    result.imag = (a.imag * b.real - a.real * b.imag) / denom;
    return result;
}

Complex ComplexScale(Complex a, double scalar) {
    Complex result;
    result.real = a.real * scalar;
    result.imag = a.imag * scalar;
    return result;
}

Complex ComplexNeg(Complex a) {
    Complex result;
    result.real = -a.real;
    result.imag = -a.imag;
    return result;
}

// Complex logarithm: ln(z) = ln(|z|) + i * arg(z)
Complex ComplexLn(Complex z) {
    Complex result;
    result.real = log(sqrt(z.real * z.real + z.imag * z.imag));
    result.imag = atan2(z.imag, z.real);
    return result;
}

// Generate prime numbers using Sieve of Eratosthenes
std::vector<int> GeneratePrimes(int limit) {
    std::vector<bool> isPrime(limit + 1, true);
    isPrime[0] = isPrime[1] = false;
    for (int i = 2; i * i <= limit; i++) {
        if (isPrime[i]) {
            for (int j = i * i; j <= limit; j += i) {
                isPrime[j] = false;
            }
        }
    }

    std::vector<int> primes;
    for (int i = 2; i <= limit; i++) {
        if (isPrime[i]) {
            primes.push_back(i);
        }
    }
    return primes;
}

// Zeta function using Euler product: ζ(z) = exp(-∑_p ln(1 - p^(-z)))
Complex Zeta(Complex z, int iterations) {
    static std::vector<int> primes;
    if (primes.empty()) {
        primes = GeneratePrimes(1000);
    }

    Complex sum = { 0.0, 0.0 };
    Complex one = { 1.0, 0.0 };
    Complex p_complex, p_neg_z, term;

    int count = 0;
    for (int p : primes) {
        if (count >= iterations) break;
        p_complex.real = (double)p;
        p_complex.imag = 0.0;

        Complex neg_z = ComplexNeg(z);
        p_neg_z = ComplexPow(p_complex, neg_z);
        term = ComplexSub(one, p_neg_z);
        Complex ln_term = ComplexLn(term);
        sum = ComplexAdd(sum, ComplexNeg(ln_term));
        count++;
    }

    double magnitude = exp(sum.real);
    Complex result;
    result.real = magnitude * cos(sum.imag);
    result.imag = magnitude * sin(sum.imag);
    return result;
}

// Draw the enhanced Zeta function visualization
void DrawEnhancedZeta(HDC hdc, int width, int height, float progress) {
    Graphics graphics(hdc);
    graphics.SetSmoothingMode(SmoothingModeAntiAlias);
    graphics.SetCompositingQuality(CompositingQualityHighQuality);
    graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);

    // Dark gradient background
    LinearGradientBrush background(
        Point(0, 0),
        Point(width, height),
        Color(255, 10, 20, 50),
        Color(255, 0, 0, 0));
    graphics.FillRectangle(&background, 0, 0, width, height);

    // Set up coordinate system
    REAL centerX = width / 2.0f;
    REAL centerY = height / 2.0f;
    REAL scale = (REAL)min(width, height) / 4.0f;
    REAL unitScale = (scale / 12.0f) * zoomFactor; // Adjusted with zoom factor

    // Draw subtle grid lines (step of 4 units)
    Pen gridPen(Color(50, 100, 100, 150), 0.3f);
    // Horizontal axis: Im(ζ(s)), up to ±32
    for (int i = -8; i <= 8; i++) { // ±32, step 4
        REAL gridPos = i * 4 * unitScale;
        graphics.DrawLine(&gridPen,
            0.0f, centerY + gridPos,
            (REAL)width, centerY + gridPos);
    }
    // Vertical axis: Re(ζ(s)), up to ±24
    for (int i = -6; i <= 6; i++) { // ±24, step 4
        REAL gridPos = i * 4 * unitScale;
        graphics.DrawLine(&gridPen,
            centerX + gridPos, 0.0f,
            centerX + gridPos, (REAL)height);
    }

    // Draw glowing axes
    LinearGradientBrush axisBrush(
        Point(0, (int)centerY),
        Point(width, (int)centerY),
        Color(150, 200, 200, 255),
        Color(50, 100, 100, 100));
    Pen axisPen(&axisBrush, 1.8f);
    graphics.DrawLine(&axisPen, 0.0f, centerY, (REAL)width, centerY);
    graphics.DrawLine(&axisPen, centerX, 0.0f, centerX, (REAL)height);

    // Draw critical line
    LinearGradientBrush criticalBrush(
        Point((int)centerX, 0),
        Point((int)centerX, height),
        Color(150, 255, 150, 50),
        Color(50, 100, 255, 50));
    Pen criticalPen(&criticalBrush, 2.0f);
    REAL criticalX = centerX + scale * 0.5f;
    graphics.DrawLine(&criticalPen, criticalX, 0.0f, criticalX, (REAL)height);

    // Compute Zeta function points and store them
    const int iterations = 200;
    const double t_start = 0.0;
    const double t_end = 30.0;
    const double t_step = 0.02;
    double t_max = t_start + progress * (t_end - t_start);

    // Collect points for the curve
    std::vector<PointF> points;
    for (double t = t_start; t <= t_max; t += t_step) {
        Complex s = { 0.5, t };
        Complex zeta = Zeta(s, iterations);

        REAL x = centerX + (REAL)zeta.imag * unitScale;
        REAL y = centerY - (REAL)zeta.real * unitScale;
        points.push_back(PointF(x, y));
    }

    // Draw the Zeta curve as a smooth spline
    GraphicsPath path;
    if (!points.empty()) {
        path.AddCurve(points.data(), (INT)points.size(), 0.5f); // Tension = 0.5 for smoothness
    }

    // Neon gradient for Zeta curve
    Color colors[] = {
        Color(200, 255, 50, 50),
        Color(200, 255, 165, 0),
        Color(200, 255, 0, 255),
        Color(200, 50, 50, 255)
    };
    REAL positions[] = { 0.0f, 0.33f, 0.67f, 1.0f };
    LinearGradientBrush pathBrush(
        Point(0, (int)(centerY - scale)),
        Point(0, (int)(centerY + scale)),
        Color(255, 255, 255, 255),
        Color(255, 255, 255, 255));
    pathBrush.SetInterpolationColors(colors, positions, 4);

    // Draw glow and main curve
    Pen glowPen(&pathBrush, 5.0f);
    glowPen.SetColor(Color(100, 255, 255, 255));
    graphics.DrawPath(&glowPen, &path);
    Pen zetaPen(&pathBrush, 2.5f);
    graphics.DrawPath(&zetaPen, &path);

    // Add annotations with adjusted positions
    Font font(L"Cambria Math", 16, FontStyleBold);
    Font smallFont(L"Cambria Math", 12, FontStyleRegular);
    SolidBrush shadowBrush(Color(80, 0, 0, 0));
    SolidBrush textBrush(Color(255, 230, 230, 230));
    StringFormat format;
    format.SetAlignment(StringAlignmentCenter);

    // Title: "ζ(s) where s = ½ + ti"
    Font bigFont(L"Cambria Math", 20, FontStyleBold);
    graphics.DrawString(L"ζ(s) where s = ½ + ti", -1, &bigFont,
        PointF(centerX + 4.0f, 24.0f), &format, &shadowBrush);
    graphics.DrawString(L"ζ(s) where s = ½ + ti", -1, &bigFont,
        PointF(centerX, 20.0f), &format, &textBrush);

    // Critical line label: "Re(s) = ½"
    graphics.DrawString(L"Re(s) = ½", -1, &font,
        PointF(criticalX + 4.0f, 60.0f), &format, &shadowBrush);
    graphics.DrawString(L"Re(s) = ½", -1, &font,
        PointF(criticalX, 56.0f), &format, &textBrush);

    // Axis label: "Im(ζ(s))"
    REAL imLabelX = (REAL)width - 100.0f;
    graphics.DrawString(L"Im(ζ(s))", -1, &font,
        PointF(imLabelX + 4.0f, centerY - 24.0f), &shadowBrush);
    graphics.DrawString(L"Im(ζ(s))", -1, &font,
        PointF(imLabelX, centerY - 20.0f), &textBrush);

    // Axis label: "Re(ζ(s))"
    graphics.DrawString(L"Re(ζ(s))", -1, &font,
        PointF(centerX + 14.0f, (REAL)height - 44.0f), &shadowBrush);
    graphics.DrawString(L"Re(ζ(s))", -1, &font,
        PointF(centerX + 10.0f, (REAL)height - 40.0f), &textBrush);

    // Coordinate labels for horizontal axis (Im(ζ(s))): -32 to 32, step 4
    for (int i = -8; i <= 8; i++) {
        int value = i * 4;
        REAL xPos = centerX + value * unitScale;
        WCHAR label[16];
        swprintf(label, 16, L"%d", value);
        graphics.DrawString(label, -1, &smallFont,
            PointF(xPos + 2.0f, centerY + 16.0f), &format, &shadowBrush);
        graphics.DrawString(label, -1, &smallFont,
            PointF(xPos, centerY + 12.0f), &format, &textBrush);
    }

    // Coordinate labels for vertical axis (Re(ζ(s))): -24 to 24, step 4
    StringFormat nearFormat;
    nearFormat.SetAlignment(StringAlignmentNear);
    for (int i = -6; i <= 6; i++) {
        int value = i * 4;
        REAL yPos = centerY - value * unitScale;
        WCHAR label[16];
        if (value == 0) {
            swprintf(label, 16, L"0");
        }
        else {
            swprintf(label, 16, L"%di", value);
        }
        graphics.DrawString(label, -1, &smallFont,
            PointF(centerX - 30.0f + 2.0f, yPos + 2.0f), &nearFormat, &shadowBrush);
        graphics.DrawString(label, -1, &smallFont,
            PointF(centerX - 30.0f, yPos), &nearFormat, &textBrush);
    }

    // Add animated non-trivial zero markers
    double zeros[] = { 14.1347, 21.0220, 25.0109, 30.4249 };
    int numZeros = sizeof(zeros) / sizeof(zeros[0]);
    for (int i = 0; i < numZeros; i++) {
        if (zeros[i] <= t_max) {
            Complex s = { 0.5, zeros[i] };
            Complex zeta = Zeta(s, iterations);
            REAL x = centerX + (REAL)zeta.imag * unitScale;
            REAL y = centerY - (REAL)zeta.real * unitScale;

            LinearGradientBrush zeroBrush(
                Point((int)(x - 10.0f), (int)(y - 10.0f)),
                Point((int)(x + 10.0f), (int)(y + 10.0f)),
                Color(200, 255, 100, 100),
                Color(0, 255, 255, 255));
            graphics.FillEllipse(&zeroBrush, x - 7.0f, y - 7.0f, 14.0f, 14.0f);

            Pen zeroPen(Color(150, 255, 255, 255), 1.0f);
            graphics.DrawEllipse(&zeroPen, x - 7.0f, y - 7.0f, 14.0f, 14.0f);
        }
    }
}

// Helper function to get PNG encoder CLSID
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid) {
    UINT num = 0, size = 0;
    Gdiplus::GetImageEncodersSize(&num, &size);
    if (size == 0) return -1;

    ImageCodecInfo* pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
    Gdiplus::GetImageEncoders(num, size, pImageCodecInfo);

    for (UINT j = 0; j < num; ++j) {
        if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) {
            *pClsid = pImageCodecInfo[j].Clsid;
            free(pImageCodecInfo);
            return j;
        }
    }

    free(pImageCodecInfo);
    return -1;
}

// Save visualization as PNG
void SaveAsPng(HWND hWnd, int width, int height, const WCHAR* filename) {
    Bitmap bitmap(width, height, PixelFormat32bppARGB);
    Graphics bitmapGraphics(&bitmap);
    bitmapGraphics.SetSmoothingMode(SmoothingModeAntiAlias);
    bitmapGraphics.SetCompositingQuality(CompositingQualityHighQuality);
    bitmapGraphics.SetTextRenderingHint(TextRenderingHintAntiAlias);

    HDC hdc = bitmapGraphics.GetHDC();
    DrawEnhancedZeta(hdc, width, height, 1.0f);
    bitmapGraphics.ReleaseHDC(hdc);

    CLSID clsid;
    if (GetEncoderClsid(L"image/png", &clsid) != -1) {
        bitmap.Save(filename, &clsid, NULL);
        char msg[512];
        snprintf(msg, sizeof(msg), "Visualization saved as %S", filename);
        MessageBoxA(hWnd, msg, "Success", MB_OK | MB_ICONINFORMATION);
    }
    else {
        MessageBoxA(hWnd, "Failed to save PNG: PNG encoder not found", "Error", MB_OK | MB_ICONERROR);
    }
}

// Open file dialog for saving PNG
void ShowSaveDialog(HWND hWnd, int width, int height) {
    WCHAR filename[MAX_PATH] = L"ZetaVisualization.png";
    OPENFILENAMEW ofn = { 0 };
    ofn.lStructSize = sizeof(OPENFILENAMEW);
    ofn.hwndOwner = hWnd;
    ofn.lpstrFilter = L"PNG Files (*.png)\0*.png\0All Files (*.*)\0*.*\0";
    ofn.lpstrFile = filename;
    ofn.nMaxFile = MAX_PATH;
    ofn.lpstrDefExt = L"png";
    ofn.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;

    if (GetSaveFileNameW(&ofn)) {
        SaveAsPng(hWnd, width, height, filename);
    }
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    static int width, height;

    switch (message) {
    case WM_CREATE:
        break;

    case WM_TIMER:
        if (wParam == ANIMATION_TIMER_ID) {
            animationProgress += ANIMATION_SPEED;
            if (animationProgress > 1.0f) {
                animationProgress = 1.0f;
                KillTimer(hWnd, ANIMATION_TIMER_ID);
                isAnimationRunning = false;
            }
            InvalidateRect(hWnd, NULL, FALSE);
        }
        break;

    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);

        RECT rect;
        GetClientRect(hWnd, &rect);
        width = rect.right;
        height = rect.bottom;

        HDC memDC = CreateCompatibleDC(hdc);
        HBITMAP memBitmap = CreateCompatibleBitmap(hdc, width, height);
        HBITMAP oldBitmap = (HBITMAP)SelectObject(memDC, memBitmap);

        HBRUSH blackBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
        FillRect(memDC, &rect, blackBrush);

        DrawEnhancedZeta(memDC, width, height, animationProgress);

        BitBlt(hdc, 0, 0, width, height, memDC, 0, 0, SRCCOPY);

        SelectObject(memDC, oldBitmap);
        DeleteObject(memBitmap);
        DeleteDC(memDC);

        EndPaint(hWnd, &ps);
        break;
    }
    case WM_SIZE:
        width = LOWORD(lParam);
        height = HIWORD(lParam);
        InvalidateRect(hWnd, NULL, TRUE);
        break;

    case WM_MOUSEWHEEL: {
        short delta = GET_WHEEL_DELTA_WPARAM(wParam);
        float zoomStep = 1.1f;

        if (delta > 0) {
            // Scroll up: Zoom in
            zoomFactor *= zoomStep;
            if (zoomFactor > 3.0f) zoomFactor = 3.0f;
        }
        else if (delta < 0) {
            // Scroll down: Zoom out
            zoomFactor /= zoomStep;
            if (zoomFactor < 0.5f) zoomFactor = 0.5f;
        }

        InvalidateRect(hWnd, NULL, FALSE);
        break;
    }

    case WM_COMMAND:
        switch (LOWORD(wParam)) {
        case 1001:
            ShowSaveDialog(hWnd, width, height);
            break;
        case 1002:
            if (!isAnimationRunning) {
                SetTimer(hWnd, ANIMATION_TIMER_ID, 16, NULL);
                isAnimationRunning = true;
            }
            break;
        case 1003:
            if (isAnimationRunning) {
                KillTimer(hWnd, ANIMATION_TIMER_ID);
                isAnimationRunning = false;
            }
            break;
        }
        break;

    case WM_KEYDOWN:
        switch (wParam) {
        case 'R': // Reset animation
        case VK_SPACE: // Also reset with Space key
            animationProgress = 0.0f;
            if (!isAnimationRunning) {
                SetTimer(hWnd, ANIMATION_TIMER_ID, 16, NULL);
                isAnimationRunning = true;
            }
            InvalidateRect(hWnd, NULL, FALSE);
            break;

        case VK_PRIOR: // Page Up: Zoom in
            zoomFactor *= 1.1f;
            if (zoomFactor > 3.0f) zoomFactor = 3.0f;
            InvalidateRect(hWnd, NULL, FALSE);
            break;

        case VK_NEXT: // Page Down: Zoom out
            zoomFactor /= 1.1f;
            if (zoomFactor < 0.5f) zoomFactor = 0.5f;
            InvalidateRect(hWnd, NULL, FALSE);
            break;
        }
        break;

    case WM_DESTROY:
        if (isAnimationRunning) {
            KillTimer(hWnd, ANIMATION_TIMER_ID);
        }
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProcA(hWnd, message, wParam, lParam);
    }
    return 0;
}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    HMENU hMenu = CreateMenu();
    HMENU hFileMenu = CreatePopupMenu();
    AppendMenuA(hFileMenu, MF_STRING, 1001, "Save As...");
    AppendMenuA(hFileMenu, MF_STRING, 1002, "Start Animation");
    AppendMenuA(hFileMenu, MF_STRING, 1003, "Pause Animation");
    AppendMenuA(hMenu, MF_POPUP, (UINT_PTR)hFileMenu, "File");

    WNDCLASSA wc = { 0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = "ZetaVisualizer";
    wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    RegisterClassA(&wc);

    HWND hWnd = CreateWindowA("ZetaVisualizer", "Riemann Zeta Function Visualizer",
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
        1200, 900, NULL, hMenu, hInstance, NULL);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    MSG msg;
    while (GetMessageA(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessageA(&msg);
    }

    DestroyMenu(hMenu);
    GdiplusShutdown(gdiplusToken);
    return (int)msg.wParam;
}


Full project on this link: https://www.mediafire.com/file/kbwfvysh83cc33x/Zeta14.rar/file (https://www.mediafire.com/file/kbwfvysh83cc33x/Zeta14.rar/file)



(https://i.postimg.cc/V085wLYK/Zeta-Visualization.png) (https://postimg.cc/V085wLYK)
Title: Re: Riemann Zeta Function
Post by: six_L on May 11, 2025, 03:38:00 PM
Hi,guga
good works!
:thumbsup:
I want to compare your image. Could you post an image of the following parameters?

step = 0.012
a = 1/2,b = [-1025.4712,-1015.1512]
Scale = 50:1
iterations = 860

Thank you in advance.

Regards
six_L
Title: Re: Riemann Zeta Function
Post by: TimoVJL on May 12, 2025, 12:23:52 AM
A test project for pure C with Pelles C.
Just for testing those functions, no graphics.
Title: Re: Riemann Zeta Function
Post by: jack on May 12, 2025, 08:17:24 AM
I updated my FreeBasic code
the Riemann zeta function (https://www.freebasic.net/forum/viewtopic.php?p=193860#p193860) now supports both negative and complex arguments
there's a bug in there somewhere, zeta(-20.1) gives the wrong sign, other than that the value is ok
the complex cosine is giving the wrong sign, any trig experts here?

fixed
sample output
Dim As complex x, y, z
Dim As Double rr, ri

for rr=-1 to 1 step .5
for ri=-1 to 1 step .5
x=complex(rr, ri)
y=zeta(x)
print using "zeta(##.####, ##.####) = ";x.re;x.im;
print using "##.################, ##.################";y.re;y.im
next
next

zeta(-1.0000, -1.0000) =  0.0168761517881836,  0.1141564804323963
zeta(-1.0000, -0.5000) = -0.0538894302820935,  0.0752004260118382
zeta(-1.0000,  0.0000) = -0.0833333333333334,  0.0000000000000000
zeta(-1.0000,  0.5000) = -0.0538894302820935, -0.0752004260118382
zeta(-1.0000,  1.0000) =  0.0168761517881836, -0.1141564804323963
zeta(-0.5000, -1.0000) = -0.0008178931340101,  0.2230716886972805
zeta(-0.5000, -0.5000) = -0.1407574606243030,  0.1580763818474494
zeta(-0.5000,  0.0000) = -0.2078862249773547,  0.0000000000000000
zeta(-0.5000,  0.5000) = -0.1407574606243030, -0.1580763818474494
zeta(-0.5000,  1.0000) = -0.0008178931340101, -0.2230716886972805
zeta( 0.0000, -1.0000) =  0.0033002236853245,  0.4181554491413226
zeta( 0.0000, -0.5000) = -0.2991978789224703,  0.3593711792648014
zeta( 0.0000,  0.0000) = -0.4999999999999991,  0.0000000000000000
zeta( 0.0000,  0.5000) = -0.2991978789224703, -0.3593711792648014
zeta( 0.0000,  1.0000) =  0.0033002236853245, -0.4181554491413226
zeta( 0.5000, -1.0000) =  0.1439364270771889,  0.7220997435316735
zeta( 0.5000, -0.5000) = -0.4593028903460181,  0.9612542845058791
zeta( 0.5000,  0.0000) = -1.4603545088095850,  0.0000000000000000
zeta( 0.5000,  0.5000) = -0.4593028903460181, -0.9612542845058791
zeta( 0.5000,  1.0000) =  0.1439364270771889, -0.7220997435316735
zeta( 1.0000, -1.0000) =  0.5821580597520036,  0.9268485643308069
zeta( 1.0000, -0.5000) =  0.5784330210993112,  1.9635494964529780
zeta( 1.0000,  0.0000) = -1.#IND000000000000, -1.#IND000000000000
zeta( 1.0000,  0.5000) =  0.5784330210993112, -1.9635494964529780
zeta( 1.0000,  1.0000) =  0.5821580597520036, -0.9268485643308069
Title: Re: Riemann Zeta Function
Post by: six_L on May 12, 2025, 06:55:52 PM
Hi,TimoVJL/jack
Thanks for sharing.

Here have the Zeta(z) 7 Nontrivial zeros.
(https://i.postimg.cc/PfLWhPXD/3.png) (https://postimages.org/)
Title: Re: Riemann Zeta Function
Post by: six_L on May 14, 2025, 04:45:55 PM
The Zeta(z) Nontrivial Zero looks like this(Attachment).
Title: Re: Riemann Zeta Function
Post by: TimoVJL on May 15, 2025, 12:59:26 AM
And what was code for it ?

Long time ago i asked form mathematician, can he show me a mathematical functions for best woman breasts and butts.
I have seen many functions for those and some of them are really good.

For woman breast some GDI functions are very good simulating  those things, but sadly those sources aren't availble right now.
Title: Re: Riemann Zeta Function
Post by: zedd on May 15, 2025, 02:20:55 AM
Quote from: TimoVJL on May 15, 2025, 12:59:26 AMAnd what was code for it ?
I'll ask an even better question...
"Where is the assembly code for any of it?", even if it is only uasm compatible and not specifically masm compatible (given the board that it is in).

Enquiring minds want to know...  :badgrin:
Title: Re: Riemann Zeta Function
Post by: six_L on May 15, 2025, 02:37:53 AM
For me, it's just despatching my interesting time when I have excess energy.

But the question of finding prime is very mysterious.
I guess:
Every Riemann Zeta(z) Nontrivial Zero corresponds to a prime number.
Zeta(0.5+bi) = 0
f(0.5+bi) = p
The larget known maxiprime today is 2^136279841-1. If someone finds the function, we'll find the next maxiprime to be easy.

QuoteLong time ago i asked form mathematician, can he show me a mathematical functions for best woman breasts and butts.
I have seen many functions for those and some of them are really good.

For woman breast some GDI functions are very good simulating  those things, but sadly those sources aren't availble right now.
This is a best APP, ought to continue.
Title: Re: Riemann Zeta Function
Post by: TimoVJL on May 15, 2025, 07:33:29 PM
I was interest, how Complex numbers are handled in pure masm.

Complex numbers are part of C since C99, not supported by Pelles C anymore.
Title: Re: Riemann Zeta Function
Post by: FORTRANS on May 16, 2025, 08:01:38 AM
Hi,

Quote from: TimoVJL on May 15, 2025, 07:33:29 PMI was interest, how Complex numbers are handled in pure masm.

   I do not think there is any direct support for complex, or imaginary,
arithmetic in MASM.  You would have to implement such actions as macros
or a set of functions.  So you would handle complex numbers with your
own code.

   Of course, someone has probably done this already, and you could use
their implementation.

Regards,

Steve N.
Title: Re: Riemann Zeta Function
Post by: daydreamer on May 16, 2025, 02:15:32 PM
Quote from: TimoVJL on May 15, 2025, 12:59:26 AMAnd what was code for it ?

Long time ago i asked form mathematician, can he show me a mathematical functions for best woman breasts and butts.
I have seen many functions for those and some of them are really good.

For woman breast some GDI functions are very good simulating  those things, but sadly those sources aren't availble right now.

Seen on TV show a woman named "fern",but there is also exist code for draw a fern plant
Might be possible with combine several curves used for creating meshes
I only have managed to created sphere with trigo curves: 1700 half circles drawing a planet,also made an egg shape

Hourglass body = vertical cosine
Title: Re: Riemann Zeta Function
Post by: TimoVJL on May 16, 2025, 09:41:30 PM
In C11 specs _Complex data type is just optional.
So many C programmers are now in same position as asm programmers.

@daydreamer, jokes needs their own topic and this is UAsm topic and i was asking masm way to handle complex numbers.
Title: Re: Riemann Zeta Function
Post by: daydreamer on May 17, 2025, 02:00:53 AM
Quote from: TimoVJL on May 16, 2025, 09:41:30 PMIn C11 specs _Complex data type is just optional.
So many C programmers are now in same position as asm programmers.

@daydreamer, jokes needs their own topic and this is UAsm topic and i was asking masm way to handle complex numbers.
I think math expert raymond might have something in his math library ???
Title: Re: Riemann Zeta Function
Post by: six_L on May 17, 2025, 02:34:29 AM
QuoteI was interest, how Complex numbers are handled in pure masm.
for example:
FpuPow proc @Fx:QWORD,@Fy:QWORD
;return: ST(0)=x^y
;x^y =2^[y*log2(x)], x > 0

finit

mov rax,@Fy
fld tbyte ptr[rax] ;y
mov rax,@Fx
fld tbyte ptr[rax] ;x,x11=x11^y
fyl2x ;y*log2(x)
;ST(0)=y*log2(x), ST(1)=zzz
fld  st ;make a second copy
;ST(0)=y*log2(x), ST(1)=y*log2(x), ST(2)=zzz
frndint ;round it to an integer
;ST(0)=int[y*log2(x)], ST(1)=y*log2(x), ST(2)=zzz
fsub st(1),st ;this will leave only a fractional portion in ST(1)
;ST(0)=int[y*log2(x)], ST(1)=y*log2(x)-int[y*log2(x)], ST(2)=zzz
fxch st(1) ;ST(0)=y*log2(x)-int[y*log2(x)], ST(1)=int[y*log2(x)], ST(2)=zzz
f2xm1 ;get the fractional power of 2 (minus 1)
;ST(0)=2ST(0)-1, ST(1)=int[y*log2(x)], ST(2)=zzz
fld1 ;ST(0)=1, ST(1)=2ST(0)-1, ST(2)=int[y*log2(x)], ST(3)=zzz
fadd ;add the 1 to ST(1) and POP ST(0)
;ST(0)=2ST(0), ST(1)=int[y*log2(x)], ST(2)=zzz
fscale ;add the integer in ST(1) to the exponent of ST(0)
;effectively multiplying the content of ST(0) by 2int
;and yielding the final result of x^y
;ST(0)=x^y, ST(1)=int[y*log2(x)], ST(2)=zzz
fstp st(1) ;the content of ST(1) has become useless
;overwrite the content of ST(1) with the result and POP ST(0)
;ST(0)=x^y, ST(1)=zzz
ret

FpuPow endp
;¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
EComplexNumberPow proc @inRealPart:QWORD,@inImaginaryPart:QWORD,@OutRealPart:QWORD,@OutImaginaryPart:QWORD
LOCAL @e:REAL10

; e^(a+bi)
; i = (-1)^0.5
; e^(a+bi) = e^a * e^[b*ln(e)i] = e^a * [cos(b.ln(e))] + e^a * [sin(b.ln(e))]i
; = e^a * [cos(b)] + e^a * [sin(b)]i

finit
; e^a
fld FP10(2.7182818284590452)
fstp @e
invoke FpuPow, addr @e, @inRealPart ; e^a

mov rax,@inImaginaryPart
fld tbyte ptr [rax] ; b
fsincos ; st0=cos(b),st1=sin(b)
fmul st(0),st(2) ; e^a * cos(b)
mov rax,@OutRealPart
fstp tbyte ptr [rax] ; @OutRealPart = e^a * cos(b)

fmul st(0),st(1) ; e^a * sin(b)
mov rax,@OutImaginaryPart
fstp tbyte ptr [rax] ; @OutImaginaryPart = e^a * sin(b)
ffree st(0)

ret
EComplexNumberPow endp
LOCAL ao:REAL10
LOCAL bo:REAL10
LOCAL a:REAL10
LOCAL b:REAL10


fld FP10(0.3)
fstp a
fld FP10(0.4)
fstp b
; e^(0.3+0.4i)
invoke EComplexNumberPow,addr a,addr b,addr ao,addr bo
; Print
; ( 1.243302295069503) + ( 0.525659779196979)i
; ao = 1.243302295069503
; bo = 0.525659779196979
Title: Re: Riemann Zeta Function
Post by: jack on May 17, 2025, 02:49:23 AM
Hi six_L
if you need some reference code here's a reasonably complete set of functions complex Riemann Zeta (https://www.freebasic.net/forum/viewtopic.php?p=193860#p193860)
Title: Re: Riemann Zeta Function
Post by: TimoVJL on May 17, 2025, 07:30:50 PM
Thanks six_L  :thumbsup:
I used it for test code for poasm.exe V13
Title: Re: Riemann Zeta Function
Post by: six_L on May 18, 2025, 09:56:16 PM
Hi,jack
Thanks you.
    '  f(k)=(k+nc)^-n

    '  inf           nc              inf                        inf
    '  ====          ====           /                          ==== B
    '  \       1     \       1      [                          \    (2*k)   (2*k-1)
    '   >    ----- =  >    ----- +  I    f(k) dk + B * f(0) -   >   ------ f  (0)
    '  /      n      /      n       ]               1          /    (2*k)!
    '  ====  k       ====  k       /                           ====
    '  k = 1         k = 1          0                          k = 1

I don't understand your Zeta formula. Do you have some detailed documentations about the formula?

1, Maybe some mistakes in calculation.
Quotezeta( 1.0000, -1.0000) =  0.5821580597520036,  0.9268485643308069
zeta( 1.0000, -0.5000) =  0.5784330210993112,  1.9635494964529780
zeta( 1.0000,  0.0000) = -1.#IND000000000000, -1.#IND000000000000
zeta( 1.0000,  0.5000) =  0.5784330210993112, -1.9635494964529780
zeta( 1.0000,  1.0000) =  0.5821580597520036, -0.9268485643308069
Quotezeta( 1.0000, -1.0000) = inf
zeta( 1.0000, -0.5000) = inf
zeta( 1.0000,  0.0000) = inf
zeta( 1.0000,  0.5000) = inf
zeta( 1.0000,  1.0000) = inf

Gamma(s).Gamma(1-s) = Pi/sin(s.Pi)     ; Euler Product.

Zeta(s) = [1/(2.pi.i)].Gamma(1-s).Int_(+inf --> +inf)[(z^(s-1).e^z)/(1-e^z)].dz ; Riemann Product.
i = (-1)^0.5
s = a + bi ; a != 1
pay attention to the (+inf --> +inf):
+inf --> ... --> (0~) --> ... --> +inf , It's not the Int_(0 --> +inf) or Int_(-inf --> +inf)

Zeta(s) = 2.Gamma(1-s).(2Pi)^(s-1).sin(Pi.s/2).Zeta(1-s)

2, some of nontrivial zeros in Riemann Zeta Function:
Quote1, ( 0.5 + 14.1347251 i ) ;  11, ( 0.5 - 14.1347251 i ) 
2, ( 0.5 + 21.0220396 i ) ;  12, ( 0.5 - 21.0220396 i )
3, ( 0.5 + 25.0108575 i ) ;  13, ( 0.5 - 25.0108575 i )
4, ( 0.5 + 30.4248761 i ) ;  14, ( 0.5 - 30.4248761 i )
5, ( 0.5 + 32.9350615 i ) ;  15, ( 0.5 - 32.9350615 i )
6, ( 0.5 + 37.5861781 i ) ;  16, ( 0.5 - 37.5861781 i )
7, ( 0.5 + 40.9187190 i ) ;  17, ( 0.5 - 40.9187190 i )
8, ( 0.5 + 43.3270732 i ) ;  18, ( 0.5 - 43.3270732 i )
9, ( 0.5 + 48.0051508 i ) ;  19, ( 0.5 - 48.0051508 i )
10,( 0.5 + 49.7738324 i ) ;  20, ( 0.5 - 49.7738324 i )

Zeta_1(s) is the aux function of Zeta(s).
Zeta_1(s) = Pi^(-s/2).Gamma(s/2).Zeta(s)
of which:
Pi^(-s/2).Gamma(s/2) is the Euler Factor.

if we want to get the Zero of Zeta(s), we need to get the Zero of Zeta_1(1-s).
for example:
Zeta(0.5+14.1 i) --> Zeta_1[1-(0.5+14.1 i)] --> Zeta_1(0.5-14.1 i)
because getting the Zero of Zeta_1(1-s) value is more easier than the Zero of Zeta(s), and the Zeros of Zeta_1(1-s) is equal the Zeros of Zeta(s).

3, Reflecting Function

Zeta(s) = 2.Gamma(1-s).(2Pi)^(s-1).sin(Pi.s/2).Zeta(1-s)
if we use (1-s) to replace the s. then the result is swaping left and right.
QuoteGamma(s).Gamma(1-s) = Pi/sin(s.Pi)
sin(2a) = 2sin(a).cos(a)
sin(a-b) = sin(a).cos(b) - cos(a).sin(b)
Zeta(1-s) = 2.Gamma(1-(1-s)).(2Pi)^((1-s)-1).sin(Pi.(1-s)/2).Zeta(1-(1-s))
          = 2.Gamma(s).(2Pi)^(-s).sin((Pi/2)-(Pi.s/2)).Zeta(s)                ;sin(Pi.(1-s)/2)
      = 2.Gamma(s).(2Pi)^(-s).[sin(Pi/2).cos(Pi.s/2)-cos(Pi/2).sin(Pi.s/2)].Zeta(s)    ;sin(Pi/2)=1, cos(Pi/2)=0
      = 2.Gamma(s).(2Pi)^(-s).cos(Pi.s/2).Zeta(s)                    ;Gamma(s) = Pi/[sin(s.Pi).Gamma(1-s)]
      = 2.(Pi/[sin(s.Pi).Gamma(1-s)]).(2Pi)^(-s).cos(Pi.s/2).Zeta(s)
      = ((2Pi).(2Pi)^(-s).cos(Pi.s/2)/[sin(s.Pi).Gamma(1-s)]).Zeta(s)        ;(2Pi).(2Pi)^(-s)=(2Pi)^(1-s)
      = ((2Pi)^(1-s).cos(Pi.s/2)/[sin(s.Pi).Gamma(1-s)]).Zeta(s)
      = (cos(Pi.s/2)/[(2Pi)^(s-1).sin(s.Pi).Gamma(1-s)]).Zeta(s)            ;(2Pi)^(1-s)= (2Pi)^[-(s-1)]

Zeta(1-s).(2Pi)^(s-1).sin(s.Pi).Gamma(1-s)/cos(Pi.s/2) = Zeta(s)            ;y=(a/b).x -->(b/a).y=x
[Gamma(1-s).(2Pi)^(s-1).sin(s.Pi)/cos(Pi.s/2)].Zeta(1-s) = Zeta(s)            ;

sin(s.Pi)/cos(Pi.s/2)=sin[2(s.Pi/2)]/cos(Pi.s/2)                    ;sin(2a) = 2sin(a).cos(a)
             =[2.sin(Pi.s/2).cos(Pi.s/2)]/cos(Pi.s/2)
             =2.sin(Pi.s/2)

[Gamma(1-s).(2Pi)^(s-1).sin(s.Pi)/cos(Pi.s/2)].Zeta(1-s) = Zeta(s)
[Gamma(1-s).(2Pi)^(s-1).2.sin(Pi.s/2)].Zeta(1-s) = Zeta(s)
2.Gamma(1-s).(2Pi)^(s-1).sin(Pi.s/2).Zeta(1-s) = Zeta(s)                ;swaped left and right.

4, the progress in prime number researching.
4.1 Adjacent prime numbers
2,3,5,7,11,13,17,...
3-2=1,17-13=4,...
p(n+1)-p(n) < 2460000    ;This means the max gap of any prime numbers less than 2460000.
4.2 there are the 45% nontrivial zeros on 1/2 line.(the attachment paper)

5,the features of Riemann Zeta function's nontrivial zeros
5.1 Count
Zeta(s)=Zeta(a+bi)=0
i = (-1)^0.5
s = a + bi ; a != 1, a = 1/2, real b > 0
CountZeros[-b,b] = 2[(b/2Pi).ln(b/2Pi) - (b/2Pi) + O(ln(b))]

5.2 Distribution
The distribution features of nontrivial zeros is similar to the quantum energy level.

6, more precision at the nontrivial zeros in Riemann Zeta(s) Function
a = 1/2, real b > 0
accurate to over 1000 decimal places.
Quote14.134725141734693790457251983562470270784257115699243175685567460149
 9634298092567649490103931715610127792029715487974367661426914698822545
 8250536323944713778041338123720597054962195586586020055556672583601077
 3700205410982661507542780517442591306254481978651072304938725629738321
 5774203952157256748093321400349904680343462673144209203773854871413783
 1735639699536542811307968053149168852906782082298049264338666734623320
 0787587617920056048680543568014444246510655975686659032286865105448594
 4432062407272703209427452221304874872092412385141835146054279015244783
 3835425453344004487936806761697300819000731393854983736215013045167269
 6838920039176285123212854220523969133425832275335164060169763527563758
 9695376749203361272092599917304270756830879511844534891800863008264831
 2516911271068291052375961797743181517071354531677549515382893784903647
 4709727019948485532209253574357909226125247736595518016975233461213977
 3160053541259267474557258778014726098308089786007125320875093959979666
 60675378381214891908864977277554420656532052405

  21.022039638771554992628479593896902777334340524902781754629520403587
 5985860688907997136585141801514195337254736424758913838650686037313212
 6211882162437574166925654471184407119403130672564622779261488733743555
 2059147397132822662470789076753814440726466841906077127569834054514028
 4399232225367882682361112892700575856532731588666042140009071151080090
 0697200279987110175847519632216496865900574811247938691638351837234278
 0734490239101038504575641215958399921001621834669113158721748057170315
 7935817977249632724076992211256634415618236051804767144227146555596737
 8124776500455584090864429169775704638165517749644524987674237036645657
 7704837992029270664315837893238009151146858070430828784147861992007607
 7604774841407827389070038957604332451278278637209093037972518237091808
 0423066673834379902282515828788761761266187138296785874562376500666242
 0780814517636976391374340593412797549697276850306200263121273830462939
 3025654143823744333440220248004533438830728387312602306547534837868011
 82789317520010690056016544152811050970637593228

  25.010857580145688763213790992562821818659549672557996672496542006745
 0920984416442778402382245580624407504710461490557783782998515227308011
 8813393358267168958722516981043873551292849372719199462297591267547869
 6628856807735070039957723114023284276873669399873219586487752250099192
 4534749762085766123345997354435583675313812659977645290374484969947911
 3789772206619930718997232254973227163005159161921279774087660006729149
 8308127930667027350849516001984670542469491796695225514179319665391273
 4145216731602337377544894146417119378489574997514110658562879690076709
 8628272186495372963239258403491387143048933588946114958624239036855617
 5189359878735685683089271444468756375337019130417377142535868018531867
 8963753268686326607197669205329533478506707982877118674944281439725425
 5165319679779912722684458969279408599507227960513612021369680647653397
 6269691774251249095257214003855886494422730332216278403670865759210329
 0789866156020484275192735141927597017849166084411074821559128310749314
 22640278339513428773126644105168571016344289902

  30.424876125859513210311897530584091320181560023715440180962146036993
 3293893332779202905842939020891106309917115273954991176332266711863193
 9180722595671424334115590685468136558072417349844724959319040811632315
 0197023484841630221400985620739718392018133021868063298225719752250023
 7468561369747124964426229779245040574906715345727886515065160832468797
 0628177810457777225878919237386290011276030973568089049253006461289272
 7530919447902003589389819427495511323917384271638108400499211198006924
 3871887296959700029100054774270689081684625934838507707996560373392659
 1631785900558390596815720730796252620549400959515892318195507003120438
 5472912847073737931700052460469858203860095171051337905912538151203525
 6495480686539474573064428698419890124742762009249476736375814720332208
 6687601457265777407119672734350479234503516187981145579444869326121291
 4417916583251901867849867644777729648215979712565041026341481014213352
 4013338332668144856154491448771220118284070765164762211312808070237683
 31017097022722833154052850963731871619582513781