// File: /workspace/github_cpp_makefile_star2_O3/misohena[P]drawstars/drawstars.cpp
// Function: void fillCircleOnEquirectangular<PixelPlotter>(Image<ColorRGB<double>>&, float, float, float, PixelPlotter)
void fillCircleOnEquirectangular(
    ImageType &canvas,
    float ra, float dec, float radius,
    F funcPlot)
{
    const int canvasW = canvas.width();
    const int canvasH = canvas.height();
    const float canvasW_2 = 0.5f * canvas.width(); //=canvasH?

    const float px2rad = float(PI / canvasH);
    const float x2rad = float(PI / canvasW_2);
    const float y2rad = float(PI / canvasH);
    const float rad2px = float(canvasH / PI);
    const float rad2x = float(canvasW_2 / PI);
    const float rad2y = float(canvasH / PI);

    const float centerX = canvasW * (360 - ra) / 360;
    const float centerY = canvasH * (90 - dec) / 180;

    const float centerXRad = centerX * x2rad;
    const float centerYRad = centerY * y2rad - (float(PI/2));
    const float sinCenterYRad = std::sin(centerYRad);
    const float cosCenterYRad = std::cos(centerYRad);

    const float radiusRad = radius * px2rad;
    const float cosRadiusRad = std::cos(radiusRad);

    // y方向の描画範囲は、中心から上下にradiusの範囲内
    // (正距円筒図法では経線上のピクセル数と度数の比率は常に一定なので)
    // x方向についてはy(dec:赤偉)ごとに計算する。
    const float ymin = std::max(std::floor(centerY - radius), 0.0f);
    const float ymax = std::min(std::ceil(centerY + radius), float(canvasH));
    for(float y = ymin; y < ymax; ++y){
        // [y, y+1)のラインを描画する。

        // y+0.5のライン上(緯線上)でのxの範囲を求める。
        //
        // - 円の中心の方角 : 赤経cx, 赤偉cy [rad]
        // - 描画する点の方角 : 赤経px, 赤偉py [rad]
        // - 円の中心の方角と描画する点の方角とのなす角 : r [rad]
        // とすると次の関係が成り立つ。
        // r=acos(sin(cy)*sin(py) + cos(cy)*cos(py)*cos(cx - px))
        //
        // これをpxについて解くと次のようになる。
        // px = -2*PI*n - acos(-sec(cy)*sec(py)*(sin(cy)*sin(py) - cos(r))) + cx
        // (nは任意の整数、secは1/cos)
        const float plotYRad = (y + 0.5f) * y2rad - float(PI/2);
        const float sinPlotYRad = sin(plotYRad);
        const float cosPlotYRad = cos(plotYRad);
        const float MIN_COS = 1e-6f;
        const float cosRX =
            (std::abs(cosCenterYRad) < MIN_COS || std::abs(cosPlotYRad) < MIN_COS) ? -2 :
            -(1/cosCenterYRad)*(1/cosPlotYRad) * (sinCenterYRad*sinPlotYRad - cosRadiusRad);
        const float rx =
            cosRX > 1 ? 0 : //緯線上は全て円の外
            cosRX < -1 ? canvasW_2 : // 緯線上は全て円の中
            std::acos(cosRX) * rad2px;
        //printf("rx=%f cosRX=%f \n", rx, cosRX);

        const float xmin = std::floor(centerX - rx);
        const float xmax = std::ceil(centerX + rx);
        for(float x = xmin; x < xmax; ++x){
            // [ (x, y) - (x+1, y+1) )の点を描画する(代表点は(x+0.5, y+0.5))。
            const float plotXRad = (x + 0.5f) * x2rad;
            // 中心(centerX, centerY)と(x+0.5, y+0.5)との距離を求める。
            const float dist = std::acos(sinCenterYRad*sinPlotYRad + cosCenterYRad*cosPlotYRad*std::cos(centerXRad - plotXRad)) * rad2px;
            const int ix = static_cast<int>(x + canvasW) % canvasW;// xは左右端で繰り返し処理。
            const int iy = static_cast<int>(y);
            if(canvas.includes(ix, iy)){ //念のため
                funcPlot(canvas.at(ix, iy), plotXRad, plotYRad, centerXRad, centerYRad, dist);
            }
        }
    }
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
subq $0xb0, %rsp
movss %xmm2, 0x8(%rsp)
movss %xmm0, 0x4(%rsp)
movq %rdi, %rbx
movl (%rdi), %r14d
movl 0x4(%rdi), %eax
xorps %xmm2, %xmm2
cvtsi2sd %eax, %xmm2
movsd 0x1d7a(%rip), %xmm0     # 0xd160
movsd %xmm2, 0x48(%rsp)
divsd %xmm2, %xmm0
cvtsd2ss %xmm0, %xmm3
movss %xmm3, 0x20(%rsp)
xorps %xmm0, %xmm0
cvtsi2ss %eax, %xmm0
movss %xmm0, 0x18(%rsp)
movss 0x1c0d(%rip), %xmm2     # 0xd01c
subss %xmm1, %xmm2
mulss %xmm0, %xmm2
divss 0x1c01(%rip), %xmm2     # 0xd020
movss %xmm2, 0x30(%rsp)
movaps %xmm2, %xmm0
mulss %xmm3, %xmm0
addss 0x1bf0(%rip), %xmm0     # 0xd024
movss %xmm0, 0x14(%rsp)
callq 0x4270
movss %xmm0, 0x2c(%rsp)
movss 0x14(%rsp), %xmm0
callq 0x4210
movaps %xmm0, 0x80(%rsp)
movss 0x20(%rsp), %xmm0
mulss 0x8(%rsp), %xmm0
callq 0x4210
movaps %xmm0, 0x60(%rsp)
movss 0x30(%rsp), %xmm0
subss 0x8(%rsp), %xmm0
callq 0x4110
xorps %xmm1, %xmm1
maxss %xmm0, %xmm1
movss %xmm1, 0x10(%rsp)
movss 0x30(%rsp), %xmm0
addss 0x8(%rsp), %xmm0
callq 0x4190
movss 0x10(%rsp), %xmm2
movss 0x18(%rsp), %xmm1
minss %xmm0, %xmm1
movss %xmm1, 0x18(%rsp)
ucomiss %xmm2, %xmm1
jbe 0xb7ec
xorps %xmm0, %xmm0
cvtsi2ss %r14, %xmm0
mulss 0x1b48(%rip), %xmm0     # 0xd014
movss %xmm0, 0x1c(%rsp)
cvtss2sd %xmm0, %xmm0
movsd 0x48(%rsp), %xmm3
movsd 0x1c7c(%rip), %xmm1     # 0xd160
divsd %xmm1, %xmm3
divsd %xmm0, %xmm1
cvtsd2ss %xmm1, %xmm1
xorps %xmm0, %xmm0
cvtsd2ss %xmm3, %xmm0
movss %xmm0, 0x28(%rsp)
leaq 0xd0(%rsp), %rax
xorps %xmm3, %xmm3
cvtsi2ss %r14d, %xmm3
movss 0x1b03(%rip), %xmm0     # 0xd018
movaps %xmm0, %xmm4
subss 0x4(%rsp), %xmm4
movss %xmm3, 0x5c(%rsp)
mulss %xmm3, %xmm4
divss %xmm0, %xmm4
movss %xmm4, 0x24(%rsp)
movss %xmm1, 0x48(%rsp)
mulss %xmm1, %xmm4
movss %xmm4, 0x58(%rsp)
movaps 0x1cb7(%rip), %xmm1     # 0xd200
movaps 0x80(%rsp), %xmm0
andps %xmm0, %xmm1
movaps %xmm1, 0x90(%rsp)
movss 0x1ac4(%rip), %xmm3     # 0xd028
movaps 0x60(%rsp), %xmm1
xorps 0x1c40(%rip), %xmm1     # 0xd1b0
movaps %xmm1, 0x60(%rsp)
movss 0x18(%rax), %xmm1
addss 0x1aaa(%rip), %xmm1     # 0xd02c
movss %xmm1, 0x54(%rsp)
divss %xmm0, %xmm3
movss %xmm3, 0x50(%rsp)
movups (%rax), %xmm0
movaps %xmm0, 0xa0(%rsp)
movsd 0x10(%rax), %xmm0
movsd %xmm0, 0x78(%rsp)
movss %xmm2, 0x10(%rsp)
movaps %xmm2, %xmm0
addss 0x1a5b(%rip), %xmm0     # 0xd014
mulss 0x20(%rsp), %xmm0
addss 0x1a5d(%rip), %xmm0     # 0xd024
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x30(%rsp)
callq 0x4080
movsd %xmm0, 0x8(%rsp)
movsd 0x30(%rsp), %xmm0
callq 0x4540
movss 0x1a41(%rip), %xmm1     # 0xd030
ucomiss 0x90(%rsp), %xmm1
xorps %xmm1, %xmm1
cvtsd2ss 0x8(%rsp), %xmm1
movss %xmm1, 0x14(%rsp)
cvtsd2ss %xmm0, %xmm0
movaps %xmm0, 0x30(%rsp)
movss 0x1c(%rsp), %xmm1
ja 0xb68c
movaps 0x30(%rsp), %xmm0
andps 0x1bdd(%rip), %xmm0     # 0xd200
movss 0x1a05(%rip), %xmm1     # 0xd030
ucomiss %xmm0, %xmm1
movss 0x1c(%rsp), %xmm1
ja 0xb68c
movss 0x19d2(%rip), %xmm2     # 0xd010
movaps %xmm2, %xmm1
divss 0x30(%rsp), %xmm1
mulss 0x50(%rsp), %xmm1
movss 0x2c(%rsp), %xmm0
mulss 0x14(%rsp), %xmm0
addss 0x60(%rsp), %xmm0
mulss %xmm1, %xmm0
xorps %xmm1, %xmm1
ucomiss %xmm2, %xmm0
ja 0xb68c
movss 0x19b5(%rip), %xmm1     # 0xd028
ucomiss %xmm0, %xmm1
movss 0x1c(%rsp), %xmm1
ja 0xb68c
callq 0x4310
movaps %xmm0, %xmm1
mulss 0x28(%rsp), %xmm1
movss %xmm1, 0x4(%rsp)
movss 0x24(%rsp), %xmm0
subss %xmm1, %xmm0
callq 0x4110
movss %xmm0, 0x8(%rsp)
movss 0x4(%rsp), %xmm0
addss 0x24(%rsp), %xmm0
callq 0x4190
movss 0x8(%rsp), %xmm3
movss %xmm0, 0x4(%rsp)
ucomiss %xmm3, %xmm0
jbe 0xb7cf
movaps 0x30(%rsp), %xmm0
mulss 0x80(%rsp), %xmm0
movaps %xmm0, 0x30(%rsp)
cvttss2si 0x10(%rsp), %ebp
movss %xmm3, 0x8(%rsp)
movaps %xmm3, %xmm1
addss 0x191d(%rip), %xmm1     # 0xd014
mulss 0x48(%rsp), %xmm1
movss 0x58(%rsp), %xmm0
subss %xmm1, %xmm0
callq 0x4210
mulss 0x30(%rsp), %xmm0
movss 0x2c(%rsp), %xmm1
mulss 0x14(%rsp), %xmm1
addss %xmm1, %xmm0
callq 0x4310
movss 0x8(%rsp), %xmm3
movaps %xmm3, %xmm1
addss 0x5c(%rsp), %xmm1
cvttss2si %xmm1, %eax
cltd
idivl %r14d
movl %edx, %eax
orl %ebp, %eax
js 0xb7b8
movl (%rbx), %eax
cmpl %edx, %eax
jbe 0xb7b8
cmpl %ebp, 0x4(%rbx)
jbe 0xb7b8
mulss 0x28(%rsp), %xmm0
divss 0x54(%rsp), %xmm0
movq 0x8(%rbx), %rcx
imull %ebp, %eax
addl %edx, %eax
leaq (%rax,%rax,2), %rax
movss 0x18a0(%rip), %xmm1     # 0xd010
subss %xmm0, %xmm1
maxss 0x18b8(%rip), %xmm1     # 0xd034
xorps %xmm0, %xmm0
sqrtss %xmm1, %xmm0
cvtss2sd %xmm0, %xmm0
movsd 0x78(%rsp), %xmm1
mulsd %xmm0, %xmm1
unpcklpd %xmm0, %xmm0            # xmm0 = xmm0[0,0]
mulpd 0xa0(%rsp), %xmm0
movupd (%rcx,%rax,8), %xmm2
addpd %xmm0, %xmm2
movupd %xmm2, (%rcx,%rax,8)
addsd 0x10(%rcx,%rax,8), %xmm1
movsd %xmm1, 0x10(%rcx,%rax,8)
addss 0x1850(%rip), %xmm3     # 0xd010
movss 0x4(%rsp), %xmm0
ucomiss %xmm3, %xmm0
ja 0xb6e6
movss 0x10(%rsp), %xmm2
addss 0x1833(%rip), %xmm2     # 0xd010
movss 0x18(%rsp), %xmm0
ucomiss %xmm2, %xmm0
ja 0xb5a8
addq $0xb0, %rsp
popq %rbx
popq %r14
popq %rbp
retq