// File: /workspace/github_cpp_makefile_star2_O1/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 %r15
pushq %r14
pushq %rbx
subq $0xb8, %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 0x1849(%rip), %xmm0     # 0xd160
movsd %xmm2, 0x40(%rsp)
divsd %xmm2, %xmm0
cvtsd2ss %xmm0, %xmm3
movss %xmm3, 0x20(%rsp)
xorps %xmm0, %xmm0
cvtsi2ss %eax, %xmm0
movss %xmm0, 0x1c(%rsp)
movss 0x16dc(%rip), %xmm2     # 0xd01c
subss %xmm1, %xmm2
mulss %xmm0, %xmm2
divss 0x16d0(%rip), %xmm2     # 0xd020
movss %xmm2, 0x30(%rsp)
movaps %xmm2, %xmm0
mulss %xmm3, %xmm0
addss 0x16bf(%rip), %xmm0     # 0xd024
movss %xmm0, 0x18(%rsp)
callq 0x4270
movss %xmm0, 0x2c(%rsp)
movss 0x18(%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, 0x14(%rsp)
movss 0x30(%rsp), %xmm0
addss 0x8(%rsp), %xmm0
callq 0x4190
movss 0x14(%rsp), %xmm2
movss 0x1c(%rsp), %xmm1
minss %xmm0, %xmm1
movss %xmm1, 0x1c(%rsp)
ucomiss %xmm2, %xmm1
jbe 0xbd45
xorps %xmm0, %xmm0
cvtsi2ss %r14, %xmm0
mulss 0x1617(%rip), %xmm0     # 0xd014
leaq 0xe0(%rsp), %rax
movss %xmm0, 0x50(%rsp)
cvtss2sd %xmm0, %xmm0
movsd 0x40(%rsp), %xmm3
movsd 0x1743(%rip), %xmm1     # 0xd160
divsd %xmm1, %xmm3
divsd %xmm0, %xmm1
cvtsd2ss %xmm1, %xmm1
xorps %xmm0, %xmm0
cvtsd2ss %xmm3, %xmm0
movss %xmm0, 0x28(%rsp)
xorps %xmm3, %xmm3
cvtsi2ss %r14d, %xmm3
movss 0x15d2(%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, 0x40(%rsp)
mulss %xmm1, %xmm4
movss %xmm4, 0x58(%rsp)
movaps 0x1786(%rip), %xmm1     # 0xd200
movaps 0x80(%rsp), %xmm0
andps %xmm0, %xmm1
movaps %xmm1, 0x90(%rsp)
movss 0x1593(%rip), %xmm3     # 0xd028
movaps 0x60(%rsp), %xmm1
xorps 0x170f(%rip), %xmm1     # 0xd1b0
movaps %xmm1, 0x60(%rsp)
divss %xmm0, %xmm3
movss %xmm3, 0x4c(%rsp)
movss 0x18(%rax), %xmm0
addss 0x156f(%rip), %xmm0     # 0xd02c
movss %xmm0, 0x54(%rsp)
movups (%rax), %xmm0
movaps %xmm0, 0xa0(%rsp)
movsd 0x10(%rax), %xmm0
movsd %xmm0, 0x78(%rsp)
movss %xmm2, 0x14(%rsp)
movaps %xmm2, %xmm0
addss 0x152a(%rip), %xmm0     # 0xd014
mulss 0x20(%rsp), %xmm0
addss 0x152c(%rip), %xmm0     # 0xd024
cvtss2sd %xmm0, %xmm0
movsd %xmm0, 0x30(%rsp)
callq 0x4080
movsd %xmm0, 0x8(%rsp)
movsd 0x30(%rsp), %xmm0
callq 0x4540
movss 0x1510(%rip), %xmm1     # 0xd030
ucomiss 0x90(%rsp), %xmm1
xorps %xmm1, %xmm1
cvtsd2ss 0x8(%rsp), %xmm1
movss %xmm1, 0x18(%rsp)
xorps %xmm2, %xmm2
cvtsd2ss %xmm0, %xmm2
movss 0x14ee(%rip), %xmm0     # 0xd034
ja 0xbb8f
movaps %xmm2, %xmm0
andps 0x16ae(%rip), %xmm0     # 0xd200
movss 0x14d6(%rip), %xmm1     # 0xd030
ucomiss %xmm0, %xmm1
movss 0x14cf(%rip), %xmm0     # 0xd034
ja 0xbb8f
movss 0x14a1(%rip), %xmm1     # 0xd010
divss %xmm2, %xmm1
mulss 0x4c(%rsp), %xmm1
movss 0x2c(%rsp), %xmm0
mulss 0x18(%rsp), %xmm0
addss 0x60(%rsp), %xmm0
mulss %xmm1, %xmm0
movaps %xmm2, 0x30(%rsp)
xorps %xmm1, %xmm1
ucomiss 0x1472(%rip), %xmm0     # 0xd010
ja 0xbbc1
movss 0x1480(%rip), %xmm1     # 0xd028
ucomiss %xmm0, %xmm1
movss 0x50(%rsp), %xmm1
ja 0xbbc1
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 0xbd28
movaps 0x30(%rsp), %xmm0
mulss 0x80(%rsp), %xmm0
movaps %xmm0, 0x30(%rsp)
cvttss2si 0x14(%rsp), %ebp
movss %xmm3, 0x8(%rsp)
movaps %xmm3, %xmm1
addss 0x13e8(%rip), %xmm1     # 0xd014
mulss 0x40(%rsp), %xmm1
movss 0x58(%rsp), %xmm0
subss %xmm1, %xmm0
callq 0x4210
mulss 0x30(%rsp), %xmm0
movss 0x2c(%rsp), %xmm1
mulss 0x18(%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 0xbd11
movl (%rbx), %eax
cmpl %edx, %eax
jbe 0xbd11
cmpl %ebp, 0x4(%rbx)
jbe 0xbd11
mulss 0x28(%rsp), %xmm0
divss 0x54(%rsp), %xmm0
imull %ebp, %eax
addl %edx, %eax
leaq (%rax,%rax,2), %r15
shlq $0x3, %r15
movss 0x135f(%rip), %xmm1     # 0xd010
subss %xmm0, %xmm1
xorps %xmm0, %xmm0
maxss %xmm0, %xmm1
addq 0x8(%rbx), %r15
ucomiss %xmm0, %xmm1
jb 0xbcce
xorps %xmm0, %xmm0
sqrtss %xmm1, %xmm0
jmp 0xbcdc
movaps %xmm1, %xmm0
callq 0x4530
movss 0x8(%rsp), %xmm3
cvtss2sd %xmm0, %xmm0
movsd 0x78(%rsp), %xmm1
mulsd %xmm0, %xmm1
unpcklpd %xmm0, %xmm0            # xmm0 = xmm0[0,0]
mulpd 0xa0(%rsp), %xmm0
movupd (%r15), %xmm2
addpd %xmm0, %xmm2
movupd %xmm2, (%r15)
addsd 0x10(%r15), %xmm1
movsd %xmm1, 0x10(%r15)
addss 0x12f7(%rip), %xmm3     # 0xd010
movss 0x4(%rsp), %xmm0
ucomiss %xmm3, %xmm0
ja 0xbc1b
movss 0x14(%rsp), %xmm2
addss 0x12da(%rip), %xmm2     # 0xd010
movss 0x1c(%rsp), %xmm0
ucomiss %xmm2, %xmm0
ja 0xbad9
addq $0xb8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
nop