text:
using ColorTypes, FixedPointNumbers
using Test

@testset "rgb promotions" begin
    @test        promote( RGB{N0f8}(0.2,0.3,0.4),  RGB(0.3,0.8,0.1)) === ( RGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8),  RGB{Float64}(0.3,0.8,0.1))
    @test_broken promote( RGB{N0f8}(0.2,0.3,0.4), RGBA(0.3,0.8,0.1)) === (RGBA{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), RGBA{Float64}(0.3,0.8,0.1))
    @test_broken promote( RGB{N0f8}(0.2,0.3,0.4), ARGB(0.3,0.8,0.1)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.3,0.8,0.1))
    @test_broken promote(RGBA{N0f8}(0.2,0.3,0.4),  RGB(0.3,0.8,0.1)) === (RGBA{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), RGBA{Float64}(0.3,0.8,0.1))
    @test_broken promote(RGBA{N0f8}(0.2,0.3,0.4), RGBA(0.3,0.8,0.1)) === (RGBA{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), RGBA{Float64}(0.3,0.8,0.1))
    @test_broken promote(ARGB{N0f8}(0.2,0.3,0.4),  RGB(0.3,0.8,0.1)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.3,0.8,0.1))
    @test_broken promote(ARGB{N0f8}(0.2,0.3,0.4), ARGB(0.3,0.8,0.1)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.3,0.8,0.1))

    @test        promote( RGB24(0.2,0.3,0.4),  RGB(0.3,0.8,0.1)) === ( RGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8),  RGB{Float64}(0.3,0.8,0.1))
    @test_broken promote( RGB24(0.2,0.3,0.4), RGBA(0.3,0.8,0.1)) === (RGBA{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), RGBA{Float64}(0.3,0.8,0.1))
    @test_broken promote( RGB24(0.2,0.3,0.4), ARGB(0.3,0.8,0.1)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.3,0.8,0.1))
    @test_broken promote(ARGB32(0.2,0.3,0.4),  RGB(0.3,0.8,0.1)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.3,0.8,0.1))
    @test_broken promote(ARGB32(0.2,0.3,0.4), ARGB(0.3,0.8,0.1)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.3,0.8,0.1))

    @test        promote( RGB24(0.2,0.3,0.4),  RGB{N0f8}(0.3,0.8,0.1)) === ( RGB{N0f8}(0.2,0.3,0.4),  RGB{N0f8}(0.3,0.8,0.1))
    @test_broken promote( RGB24(0.2,0.3,0.4), RGBA{N0f8}(0.3,0.8,0.1)) === (RGBA{N0f8}(0.2,0.3,0.4), RGBA{N0f8}(0.3,0.8,0.1))
    @test_broken promote( RGB24(0.2,0.3,0.4), ARGB{N0f8}(0.3,0.8,0.1)) === (ARGB{N0f8}(0.2,0.3,0.4), ARGB{N0f8}(0.3,0.8,0.1))
    @test_broken promote(ARGB32(0.2,0.3,0.4),  RGB{N0f8}(0.3,0.8,0.1)) === (ARGB{N0f8}(0.2,0.3,0.4), ARGB{N0f8}(0.3,0.8,0.1))
    @test_broken promote(ARGB32(0.2,0.3,0.4), ARGB{N0f8}(0.3,0.8,0.1)) === (ARGB{N0f8}(0.2,0.3,0.4), ARGB{N0f8}(0.3,0.8,0.1))

    @test_broken promote(RGBX{N0f8}(0.2,0.3,0.4),  RGB(0.3,0.8,0.1)) === (RGBX{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), RGBX{Float64}(0.3,0.8,0.1))
    @test_broken promote(RGBX{N0f8}(0.2,0.3,0.4), RGBA(0.3,0.8,0.1)) === (RGBA{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), RGBA{Float64}(0.3,0.8,0.1))
    @test_broken promote(RGBX{N0f8}(0.2,0.3,0.4), ARGB(0.3,0.8,0.1)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.3,0.8,0.1))
    @test_broken promote(XRGB{N0f8}(0.2,0.3,0.4),  RGB(0.3,0.8,0.1)) === (XRGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), XRGB{Float64}(0.3,0.8,0.1))
    @test_broken promote(XRGB{N0f8}(0.2,0.3,0.4), RGBA(0.3,0.8,0.1)) === (RGBA{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), RGBA{Float64}(0.3,0.8,0.1))
    @test_broken promote(XRGB{N0f8}(0.2,0.3,0.4), ARGB(0.3,0.8,0.1)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.3,0.8,0.1))

    @test_broken promote(RGBX(0.2,0.3,0.4),  RGB{N0f8}(0.3,0.8,0.1)) === (RGBX{Float64}(0.2,0.3,0.4), RGBX{Float64}(0.3N0f8,0.8N0f8,0.1N0f8))
    @test_broken promote(RGBX(0.2,0.3,0.4), RGBA{N0f8}(0.3,0.8,0.1)) === (RGBA{Float64}(0.2,0.3,0.4), RGBA{Float64}(0.3N0f8,0.8N0f8,0.1N0f8))
    @test_broken promote(RGBX(0.2,0.3,0.4), ARGB{N0f8}(0.3,0.8,0.1)) === (ARGB{Float64}(0.2,0.3,0.4), ARGB{Float64}(0.3N0f8,0.8N0f8,0.1N0f8))
    @test_broken promote(XRGB(0.2,0.3,0.4),  RGB{N0f8}(0.3,0.8,0.1)) === (XRGB{Float64}(0.2,0.3,0.4), XRGB{Float64}(0.3N0f8,0.8N0f8,0.1N0f8))
    @test_broken promote(XRGB(0.2,0.3,0.4), RGBA{N0f8}(0.3,0.8,0.1)) === (RGBA{Float64}(0.2,0.3,0.4), RGBA{Float64}(0.3N0f8,0.8N0f8,0.1N0f8))
    @test_broken promote(XRGB(0.2,0.3,0.4), ARGB{N0f8}(0.3,0.8,0.1)) === (ARGB{Float64}(0.2,0.3,0.4), ARGB{Float64}(0.3N0f8,0.8N0f8,0.1N0f8))
end

@testset "hsv promotions" begin
    @test_broken promote( HSV{Float32}(100,0.3,0.4),  HSV(200,0.8,0.1)) === ( HSV{Float64}(100,0.3f0,0.4f0),  HSV{Float64}(200,0.8,0.1))
    @test_broken promote( HSV{Float32}(100,0.3,0.4), HSVA(200,0.8,0.1)) === (HSVA{Float64}(100,0.3f0,0.4f0), HSVA{Float64}(200,0.8,0.1))
    @test_broken promote( HSV{Float32}(100,0.3,0.4), AHSV(200,0.8,0.1)) === (AHSV{Float64}(100,0.3f0,0.4f0), AHSV{Float64}(200,0.8,0.1))
    @test_broken promote(HSVA{Float32}(100,0.3,0.4),  HSV(200,0.8,0.1)) === (HSVA{Float64}(100,0.3f0,0.4f0), HSVA{Float64}(200,0.8,0.1))
    @test_broken promote(HSVA{Float32}(100,0.3,0.4), HSVA(200,0.8,0.1)) === (HSVA{Float64}(100,0.3f0,0.4f0), HSVA{Float64}(200,0.8,0.1))
    @test_broken promote(AHSV{Float32}(100,0.3,0.4),  HSV(200,0.8,0.1)) === (AHSV{Float64}(100,0.3f0,0.4f0), AHSV{Float64}(200,0.8,0.1))
    @test_broken promote(AHSV{Float32}(100,0.3,0.4), AHSV(200,0.8,0.1)) === (AHSV{Float64}(100,0.3f0,0.4f0), AHSV{Float64}(200,0.8,0.1))
end

@testset "gray promotions" begin
    @test        promote( Gray{N0f8}(0.2),  Gray(0.3)) === ( Gray{Float64}(0.2N0f8),  Gray{Float64}(0.3))
    @test_broken promote( Gray{N0f8}(0.2), GrayA(0.3)) === (GrayA{Float64}(0.2N0f8), GrayA{Float64}(0.3))
    @test_broken promote( Gray{N0f8}(0.2), AGray(0.3)) === (AGray{Float64}(0.2N0f8), AGray{Float64}(0.3))
    @test_broken promote(GrayA{N0f8}(0.2),  Gray(0.3)) === (GrayA{Float64}(0.2N0f8), GrayA{Float64}(0.3))
    @test_broken promote(GrayA{N0f8}(0.2), GrayA(0.3)) === (GrayA{Float64}(0.2N0f8), GrayA{Float64}(0.3))
    @test_broken promote(AGray{N0f8}(0.2),  Gray(0.3)) === (AGray{Float64}(0.2N0f8), AGray{Float64}(0.3))
    @test_broken promote(AGray{N0f8}(0.2), AGray(0.3)) === (AGray{Float64}(0.2N0f8), AGray{Float64}(0.3))

    @test        promote( Gray24(0.2),  Gray(0.3)) === ( Gray{Float64}(0.2N0f8),  Gray{Float64}(0.3))
    @test_broken promote( Gray24(0.2), GrayA(0.3)) === (GrayA{Float64}(0.2N0f8), GrayA{Float64}(0.3))
    @test_broken promote( Gray24(0.2), AGray(0.3)) === (AGray{Float64}(0.2N0f8), AGray{Float64}(0.3))
    @test_broken promote(AGray32(0.2),  Gray(0.3)) === (AGray{Float64}(0.2N0f8), AGray{Float64}(0.3))
    @test_broken promote(AGray32(0.2), AGray(0.3)) === (AGray{Float64}(0.2N0f8), AGray{Float64}(0.3))
    @test        promote( Gray24(0.2),  Gray{N0f8}(0.3)) === ( Gray{N0f8}(0.2),  Gray{N0f8}(0.3))
    @test_broken promote( Gray24(0.2), GrayA{N0f8}(0.3)) === (GrayA{N0f8}(0.2), GrayA{N0f8}(0.3))
    @test_broken promote( Gray24(0.2), AGray{N0f8}(0.3)) === (AGray{N0f8}(0.2), AGray{N0f8}(0.3))
    @test_broken promote(AGray32(0.2),  Gray{N0f8}(0.3)) === (AGray{N0f8}(0.2), AGray{N0f8}(0.3))
    @test_broken promote(AGray32(0.2), AGray{N0f8}(0.3)) === (AGray{N0f8}(0.2), AGray{N0f8}(0.3))
end

@testset "rgb and gray promotions" begin
    @test promote( RGB(0.2,0.3,0.4),  Gray(0.8)) === (RGB{Float64}(0.2,0.3,0.4), RGB{Float64}(0.8,0.8,0.8))
    @test promote( RGB(0.2,0.3,0.4), GrayA(0.8)) === (RGBA{Float64}(0.2,0.3,0.4,1), RGBA{Float64}(0.8,0.8,0.8,1))
    @test promote( RGB(0.2,0.3,0.4), AGray(0.8)) === (ARGB{Float64}(0.2,0.3,0.4,1), ARGB{Float64}(0.8,0.8,0.8,1))
    @test promote(RGBA(0.2,0.3,0.4),  Gray(0.8)) === (RGBA{Float64}(0.2,0.3,0.4,1), RGBA{Float64}(0.8,0.8,0.8,1))
    @test promote(RGBA(0.2,0.3,0.4), GrayA(0.8)) === (RGBA{Float64}(0.2,0.3,0.4,1), RGBA{Float64}(0.8,0.8,0.8,1))
    @test promote(RGBA(0.2,0.3,0.4), AGray(0.8)) === (RGBA{Float64}(0.2,0.3,0.4,1), RGBA{Float64}(0.8,0.8,0.8,1))
    @test promote(ARGB(0.2,0.3,0.4),  Gray(0.8)) === (ARGB{Float64}(0.2,0.3,0.4,1), ARGB{Float64}(0.8,0.8,0.8,1))
    @test promote(ARGB(0.2,0.3,0.4), GrayA(0.8)) === (ARGB{Float64}(0.2,0.3,0.4,1), ARGB{Float64}(0.8,0.8,0.8,1))
    @test promote(ARGB(0.2,0.3,0.4), AGray(0.8)) === (ARGB{Float64}(0.2,0.3,0.4,1), ARGB{Float64}(0.8,0.8,0.8,1))

    @test promote( RGB{N0f8}(0.2,0.3,0.4),  Gray(0.8)) === (RGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), RGB{Float64}(0.8,0.8,0.8))
    @test promote( RGB{N0f8}(0.2,0.3,0.4), GrayA(0.8)) === (RGBA{Float64}(0.2N0f8,0.3N0f8,0.4N0f8,1), RGBA{Float64}(0.8,0.8,0.8,1))
    @test promote( RGB{N0f8}(0.2,0.3,0.4), AGray(0.8)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8,1), ARGB{Float64}(0.8,0.8,0.8,1))
    @test promote(RGBA{N0f8}(0.2,0.3,0.4),  Gray(0.8)) === (RGBA{Float64}(0.2N0f8,0.3N0f8,0.4N0f8,1), RGBA{Float64}(0.8,0.8,0.8,1))
    @test promote(RGBA{N0f8}(0.2,0.3,0.4), GrayA(0.8)) === (RGBA{Float64}(0.2N0f8,0.3N0f8,0.4N0f8,1), RGBA{Float64}(0.8,0.8,0.8,1))
    @test promote(RGBA{N0f8}(0.2,0.3,0.4), AGray(0.8)) === (RGBA{Float64}(0.2N0f8,0.3N0f8,0.4N0f8,1), RGBA{Float64}(0.8,0.8,0.8,1))
    @test promote(ARGB{N0f8}(0.2,0.3,0.4),  Gray(0.8)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8,1), ARGB{Float64}(0.8,0.8,0.8,1))
    @test promote(ARGB{N0f8}(0.2,0.3,0.4), GrayA(0.8)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8,1), ARGB{Float64}(0.8,0.8,0.8,1))
    @test promote(ARGB{N0f8}(0.2,0.3,0.4), AGray(0.8)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8,1), ARGB{Float64}(0.8,0.8,0.8,1))

    @test promote( RGB(0.2,0.3,0.4),  Gray{N0f8}(0.8)) === (RGB{Float64}(0.2,0.3,0.4), RGB{Float64}(0.8N0f8,0.8N0f8,0.8N0f8))
    @test promote( RGB(0.2,0.3,0.4), GrayA{N0f8}(0.8)) === (RGBA{Float64}(0.2,0.3,0.4,1), RGBA{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))
    @test promote( RGB(0.2,0.3,0.4), AGray{N0f8}(0.8)) === (ARGB{Float64}(0.2,0.3,0.4,1), ARGB{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))
    @test promote(RGBA(0.2,0.3,0.4),  Gray{N0f8}(0.8)) === (RGBA{Float64}(0.2,0.3,0.4,1), RGBA{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))
    @test promote(RGBA(0.2,0.3,0.4), GrayA{N0f8}(0.8)) === (RGBA{Float64}(0.2,0.3,0.4,1), RGBA{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))
    @test promote(RGBA(0.2,0.3,0.4), AGray{N0f8}(0.8)) === (RGBA{Float64}(0.2,0.3,0.4,1), RGBA{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))
    @test promote(ARGB(0.2,0.3,0.4),  Gray{N0f8}(0.8)) === (ARGB{Float64}(0.2,0.3,0.4,1), ARGB{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))
    @test promote(ARGB(0.2,0.3,0.4), GrayA{N0f8}(0.8)) === (ARGB{Float64}(0.2,0.3,0.4,1), ARGB{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))
    @test promote(ARGB(0.2,0.3,0.4), AGray{N0f8}(0.8)) === (ARGB{Float64}(0.2,0.3,0.4,1), ARGB{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))

    @test_broken promote( RGB24(0.2,0.3,0.4),  Gray(0.8)) === ( RGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8),  RGB{Float64}(0.8,0.8,0.8,0.1))
    @test_broken promote( RGB24(0.2,0.3,0.4), GrayA(0.8)) === (RGBA{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), RGBA{Float64}(0.8,0.8,0.8,0.1))
    @test_broken promote( RGB24(0.2,0.3,0.4), AGray(0.8)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.8,0.8,0.8,0.1))
    @test_broken promote(ARGB32(0.2,0.3,0.4),  Gray(0.8)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.8,0.8,0.8,0.1))
    @test_broken promote(ARGB32(0.2,0.3,0.4), GrayA(0.8)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.8,0.8,0.8,0.1))
    @test_broken promote(ARGB32(0.2,0.3,0.4), AGray(0.8)) === (ARGB{Float64}(0.2N0f8,0.3N0f8,0.4N0f8), ARGB{Float64}(0.8,0.8,0.8,0.1))

    @test promote( RGB(0.2,0.3,0.4),  Gray24(0.8)) === (RGB{Float64}(0.2,0.3,0.4), RGB{Float64}(0.8N0f8,0.8N0f8,0.8N0f8))
    @test promote( RGB(0.2,0.3,0.4), AGray32(0.8)) === (ARGB{Float64}(0.2,0.3,0.4,1), ARGB{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))
    @test promote(RGBA(0.2,0.3,0.4),  Gray24(0.8)) === (RGBA{Float64}(0.2,0.3,0.4,1), RGBA{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))
    @test promote(RGBA(0.2,0.3,0.4), AGray32(0.8)) === (RGBA{Float64}(0.2,0.3,0.4,1), RGBA{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))
    @test promote(ARGB(0.2,0.3,0.4),  Gray24(0.8)) === (ARGB{Float64}(0.2,0.3,0.4,1), ARGB{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))
    @test promote(ARGB(0.2,0.3,0.4), AGray32(0.8)) === (ARGB{Float64}(0.2,0.3,0.4,1), ARGB{Float64}(0.8N0f8,0.8N0f8,0.8N0f8,1))

    @test_broken promote( RGB24(0.2,0.3,0.4),  Gray24(0.8)) === (RGB24(0.2,0.3,0.4), RGB24(0.8,0.8,0.8))
    @test_broken promote( RGB24(0.2,0.3,0.4), AGray32(0.8)) === (ARGB32(0.2,0.3,0.4,1), ARGB32(0.8,0.8,0.8,1))
    @test_broken promote(ARGB32(0.2,0.3,0.4),  Gray24(0.8)) === (ARGB32(0.2,0.3,0.4,1), ARGB32(0.8,0.8,0.8,1))
    @test_broken promote(ARGB32(0.2,0.3,0.4), AGray32(0.8)) === (ARGB32(0.2,0.3,0.4,1), ARGB32(0.8,0.8,0.8,1))

    @test promote(RGB(0.2,0.3,0.4), Gray{Bool}(1)) === (RGB{Float64}(0.2,0.3,0.4), RGB{Float64}(1,1,1))
    @test promote(RGB{N0f8}(0.2,0.3,0.4), Gray{Bool}(1)) === (RGB{N0f8}(0.2,0.3,0.4), RGB{N0f8}(1,1,1))
end

@testset "rgb conversions with abstract types" begin
    c = RGB(1, 0.6, 0)
    @test convert(Colorant, c) === RGB{Float64}(1, 0.6, 0)
    @test convert(Colorant{N0f8}, c) === RGB{N0f8}(1, 0.6, 0)
    @test_broken convert(Colorant{Float32,3}, c) === RGB{Float32}(1, 0.6, 0)
    @test convert(Color, c) === RGB{Float64}(1, 0.6, 0)
    @test convert(Color{N0f8}, c) === RGB{N0f8}(1, 0.6, 0)
    @test convert(Color{Float32}, c) === RGB{Float32}(1, 0.6, 0)
    @test convert(AbstractRGB, c) === RGB{Float64}(1, 0.6, 0)
    @test convert(AbstractRGB{N0f8}, c) === RGB{N0f8}(1, 0.6, 0)
    @test_throws ErrorException convert(TransparentColor, c)
    @test_throws ErrorException convert(TransparentColor{RGB{N0f8}}, c)
    @test_throws ErrorException convert(TransparentColor{RGB{N0f8},N0f8}, c)
    @test_throws ErrorException convert(TransparentColor{RGB{N0f8},N0f8,2}, c)
    @test convert(AlphaColor, c) === ARGB{Float64}(1, 0.6, 0, 1)
    @test_broken convert(AlphaColor{RGB{N0f8}}, c) === ARGB{N0f8}(1, 0.6, 0, 1)
    @test convert(AlphaColor{RGB{N0f8},N0f8}, c) === ARGB{N0f8}(1, 0.6, 0, 1)
    @test convert(AlphaColor{RGB{N0f8},N0f8,4}, c) === ARGB{N0f8}(1, 0.6, 0, 1)
    @test convert(ColorAlpha, c) === RGBA{Float64}(1, 0.6, 0, 1)
    @test_broken convert(ColorAlpha{RGB{N0f8}}, c) === RGBA{N0f8}(1, 0.6, 0, 1)
    @test convert(ColorAlpha{RGB{N0f8},N0f8}, c) === RGBA{N0f8}(1, 0.6, 0, 1)
    @test convert(ColorAlpha{RGB{N0f8},N0f8,4}, c) === RGBA{N0f8}(1, 0.6, 0, 1)

    ac = ARGB(1, 0.6, 0, 0.8)
    @test convert(Colorant, ac) === ARGB{Float64}(1, 0.6, 0, 0.8)
    @test convert(Colorant{N0f8}, ac) === ARGB{N0f8}(1, 0.6, 0, 0.8)
    @test_broken convert(Colorant{Float32,3}, ac) === RGB{Float32}(1, 0.6, 0)
    @test convert(Color, ac) === RGB{Float64}(1, 0.6, 0)
    @test_broken convert(AbstractRGB, ac) === RGB{Float64}(1, 0.6, 0)
    @test_broken convert(AbstractRGB{N0f8}, ac) === RGB{N0f8}(1, 0.6, 0)
    @test convert(TransparentColor, ac) == ARGB{Float64}(1, 0.6, 0, 0.8)
    @test convert(AlphaColor, ac) === ARGB{Float64}(1, 0.6, 0, 0.8) # issue #126
    @test convert(ColorAlpha, ac) === RGBA{Float64}(1, 0.6, 0, 0.8) # issue #126

    ca = RGBA(1, 0.6, 0, 0.8)
    @test convert(Colorant, ca) === RGBA{Float64}(1, 0.6, 0, 0.8)
    @test convert(Colorant{N0f8}, ca) === RGBA{N0f8}(1, 0.6, 0, 0.8)
    @test_broken convert(Colorant{Float32,3}, ca) === RGB{Float32}(1, 0.6, 0)
    @test convert(Color, ca) === RGB{Float64}(1, 0.6, 0)
    @test_broken convert(AbstractRGB, ca) === RGB{Float64}(1, 0.6, 0)
    @test_broken convert(AbstractRGB{N0f8}, ca) === RGB{N0f8}(1, 0.6, 0)
    @test convert(TransparentColor, ca) == RGBA{Float64}(1, 0.6, 0, 0.8)
    @test convert(AlphaColor, ca) === ARGB{Float64}(1, 0.6, 0, 0.8) # issue #126
    @test convert(ColorAlpha, ca) === RGBA{Float64}(1, 0.6, 0, 0.8) # issue #126

    rgb24 = RGB24(1, 0.6, 0)
    @test convert(Colorant, rgb24) === RGB24(1, 0.6, 0)
    @test convert(Colorant{N0f8}, rgb24) === RGB24(1, 0.6, 0)
    @test_broken convert(Colorant{Float32,3}, rgb24) === RGB{Float32}(1, 0.6, 0)
    @test convert(Color, rgb24) === RGB24(1, 0.6, 0)
    @test convert(AbstractRGB, rgb24) === RGB24(1, 0.6, 0)
    @test convert(AbstractRGB{N0f8}, rgb24) === RGB24(1, 0.6, 0)
    @test_throws ErrorException convert(TransparentColor, rgb24)
    @test convert(AlphaColor, rgb24) === ARGB32(1, 0.6, 0, 1)
    @test_throws MethodError convert(ColorAlpha, rgb24)

    argb32 = ARGB32(1, 0.6, 0, 0.8)
    @test convert(Colorant, argb32) === ARGB32(1, 0.6, 0, 0.8)
    @test convert(Colorant{N0f8}, argb32) === ARGB32(1, 0.6, 0, 0.8)
    @test_broken convert(Colorant{Float32,3}, argb32) === RGB{Float32}(1, 0.6, 0)
    @test convert(Color, argb32) === RGB24(1, 0.6, 0)
    @test_broken convert(AbstractRGB, argb32) === RGB24(1, 0.6, 0)
    @test_broken convert(AbstractRGB{N0f8}, argb32) === RGB24(1, 0.6, 0)
    @test convert(TransparentColor, argb32) === ARGB32(1, 0.6, 0, 0.8)
    @test convert(AlphaColor, argb32) === ARGB32(1, 0.6, 0, 0.8)
    @test_throws MethodError convert(ColorAlpha, argb32)

    @test convert(AbstractARGB{RGB,N0f8}, c, 0.2) === ARGB{N0f8}(1, 0.6, 0, 0.2)
    @test convert(AbstractRGBA{RGB,N0f8}, c, 0.2) === RGBA{N0f8}(1, 0.6, 0, 0.2)
    @test_broken convert(AbstractARGB{RGB24,N0f8}, rgb24, 0.2) === ARGB32(1, 0.6, 0, 0.2)
    @test_throws MethodError convert(AbstractARGB{RGB,N0f8}, ac, 0.2)
    @test_throws MethodError convert(AbstractARGB{RGB,N0f8}, ca, 0.2)
    @test_throws ErrorException convert(AbstractARGB{RGB,N0f8}, rgb24, 0.2)
    @test_throws MethodError convert(AbstractARGB{RGB,N0f8}, argb32, 0.2)
end

@testset "gray conversions with abstract types" begin
    c = Gray(0.4)
    @test convert(Colorant, c) === Gray{Float64}(0.4)
    @test convert(Colorant{N0f8}, c) === Gray{N0f8}(0.4)
    @test_broken convert(Colorant{Float32,1}, c) === Gray{Float32}(0.4)
    @test convert(Color, c) === Gray{Float64}(0.4)
    @test_throws ErrorException convert(TransparentColor, c)
    @test convert(AlphaColor, c) === AGray{Float64}(0.4, 1)
    @test convert(ColorAlpha, c) === GrayA{Float64}(0.4, 1)

    ac = AGray(0.4, 0.8)
    @test convert(Colorant, ac) === AGray{Float64}(0.4, 0.8)
    @test convert(Colorant{N0f8}, ac) === AGray{N0f8}(0.4, 0.8)
    @test_broken convert(Colorant{Float32,1}, ac) === Gray{Float32}(0.4, 0.8)
    @test convert(Color, ac) === Gray{Float64}(0.4)
    @test convert(TransparentColor, ac) == AGray{Float64}(0.4, 0.8)
    @test convert(AlphaColor, ac) === AGray{Float64}(0.4, 0.8)
    @test convert(ColorAlpha, ac) === GrayA{Float64}(0.4, 0.8)

    ca = GrayA(0.4, 0.8)
    @test convert(Colorant, ca) === GrayA{Float64}(0.4, 0.8)
    @test convert(Colorant{N0f8}, ca) === GrayA{N0f8}(0.4, 0.8)
    @test_broken convert(Colorant{Float32,1}, ca) === Gray{Float32}(0.4)
    @test convert(Color, ca) === Gray{Float64}(0.4)
    @test convert(TransparentColor, ca) == GrayA{Float64}(0.4, 0.8)
    @test convert(AlphaColor, ca) === AGray{Float64}(0.4, 0.8)
    @test convert(ColorAlpha, ca) === GrayA{Float64}(0.4, 0.8)

    gray24 = Gray24(0.4)
    @test convert(Colorant, gray24) === Gray24(0.4)
    @test convert(Colorant{N0f8}, gray24) === Gray24(0.4)
    @test_broken convert(Colorant{Float32,1}, gray24) === Gray{Float32}(0.4)
    @test convert(Color, gray24) === Gray24(0.4)
    @test_throws ErrorException convert(TransparentColor, gray24)
    @test convert(AlphaColor, gray24) === AGray32(0.4, 1)
    @test_throws MethodError convert(ColorAlpha, gray24) # TODO: need docs

    agray32 = AGray32(0.4, 0.8)
    @test convert(Colorant, agray32) === AGray32(0.4, 0.8)
    @test convert(Colorant{N0f8}, agray32) === AGray32(0.4, 0.8)
    @test_broken convert(Colorant{Float32,1}, agray32) === Gray{Float32}(0.4)
    @test convert(Color, agray32) === Gray24(0.4)
    @test convert(TransparentColor, agray32) === AGray32(0.4, 0.8)
    @test convert(AlphaColor, agray32) === AGray32(0.4, 0.8)
    @test_throws MethodError convert(ColorAlpha, agray32) # TODO: need docs

    @test convert(AbstractAGray{Gray,N0f8}, c, 0.2) === AGray{N0f8}(0.4, 0.2)
    @test convert(AbstractGrayA{Gray,N0f8}, c, 0.2) === GrayA{N0f8}(0.4, 0.2)
    # the following is ok, but not consistent with the case of RGB24
    @test convert(AbstractAGray{Gray,N0f8}, gray24, 0.2) === AGray{N0f8}(0.4, 0.2)
    @test_broken convert(AbstractAGray{Gray24,N0f8}, gray24, 0.2) === AGray32(0.4, 0.2)
    @test_throws MethodError convert(AbstractAGray{Gray,N0f8}, ac, 0.2)
    @test_throws MethodError convert(AbstractAGray{Gray,N0f8}, ca, 0.2)
    @test_throws MethodError convert(AbstractAGray{Gray,N0f8}, agray32, 0.2)
end

@testset "conversions from/to real numbers" begin
    @test convert(Float64, Gray(0.6)) === 0.6
    @test Float32(Gray(0.6)) === 0.6f0
    @test float(Gray(0.6)) === 0.6
    @test real(Gray(0.6)) === 0.6

    @test convert(N0f8, Gray24(0.6)) === N0f8(0.6)
    @test convert(Float64, Gray24(0.6)) === 0.6

    @test convert(Gray, 0.6) === Gray{Float64}(0.6)
    @test convert(Gray, 0.6f0) === Gray{Float32}(0.6)
    @test convert(Gray, 0.6N0f8) === Gray{N0f8}(0.6)
    @test convert(Gray, true) === Gray{Bool}(1)
    @test convert(Gray, false) === Gray{Bool}(0)
    @test convert(Gray, 1) === Gray{N0f8}(1)

    @test convert(Gray{N0f16}, 0.6) === Gray{N0f16}(0.6)
    @test convert(Gray{N0f16}, 0.6f0) === Gray{N0f16}(0.6)
    @test convert(Gray{N0f16}, 0.6N0f8) === Gray{N0f16}(0.6)

    @test convert(GrayA{N0f8}, 0.6) === GrayA{N0f8}(0.6, 1)
    @test convert(AGray{N0f8}, 0.6) === AGray{N0f8}(0.6, 1)

    @test convert(Gray24, 0.6) === Gray24(0.6)
    @test convert(Gray24, 0.6f0) === Gray24(0.6)
    @test convert(Gray24, 0.6N0f8) === Gray24(0.6)

    @test convert(AGray32, 0.6) === AGray32(0.6, 1)
    @test convert(AGray32, 0.6f0) === AGray32(0.6, 1)
    @test convert(AGray32, 0.6N0f8) === AGray32(0.6, 1)
    @test convert(AGray32, 0.6, 0.8) === AGray32(0.6, 0.8)
    @test convert(AGray32, 0, 1) === AGray32(0, 1)

    @test_throws MethodError convert(Colorant, 0.6)
    @test_throws MethodError convert(Color, 0.6)
    @test_throws ErrorException convert(Color{N0f8,1}, 0.6)

    @test_throws MethodError convert(GrayA, 0.6, 0.8)
    @test_throws MethodError convert(AGray, 0, 1)

    @test convert(Gray, 2.0) === Gray{Float64}(2.0)
    @test_throws ArgumentError convert(Gray, 2)

    @test convert(RGB24, 0.6) === RGB24(0.6, 0.6, 0.6)
    @test convert(ARGB32, 0.6) === ARGB32(0.6, 0.6, 0.6, 1)

    @test_throws MethodError convert(RGB, 0.6)
end

@testset "conversions from rgb to rgb" begin
    Crgb = filter(T -> T <: AbstractRGB, ColorTypes.parametric3)
    Ctransparent = unique(vcat(coloralpha.(Crgb), alphacolor.(Crgb)))
    @testset "$C conversions" for C in Crgb
        @test convert(C, C{Float64}(1,0.6,0)) === C{Float64}(1,0.6,0)
        @test convert(C{N0f8}, C{Float64}(1,0.6,0)) === C{N0f8}(1,0.6,0)
        @test convert(C, RGB24(1,0.6,0)) === C{N0f8}(1,0.6,0)
        @test convert(RGB24, C(1,0.6,0)) === RGB24(1,0.6,0)
        @test convert(C, ARGB32(1,0.6,0,0.8)) === C{N0f8}(1,0.6,0)
        @test convert(ARGB32, C(1,0.6,0)) === ARGB32(1,0.6,0)
        @test_broken convert(ARGB32, C(1,0.6,0), 0.2) === ARGB32(1,0.6,0,0.2)
    end
    @testset "$C conversions" for C in Ctransparent
        @test convert(C, C{Float64}(1,0.6,0,0.8)) === C{Float64}(1,0.6,0,0.8)
        @test convert(C{N0f8}, C{Float64}(1,0.6,0,0.8)) === C{N0f8}(1,0.6,0,0.8)
        @test convert(C, RGB24(1,0.6,0)) === C{N0f8}(1,0.6,0,1)
        @test_broken convert(C, RGB24(1,0.6,0), 0.2) === C{N0f8}(1,0.6,0,0.2)
        @test convert(RGB24, C(1,0.6,0,0.8)) === RGB24(1,0.6,0)
        @test convert(C, ARGB32(1,0.6,0,0.8)) === C{N0f8}(1,0.6,0,0.8)
        @test convert(ARGB32, C(1,0.6,0,0.8)) === ARGB32(1,0.6,0,0.8)
    end
    @test convert(RGB24, RGB24(1,0.6,0)) === RGB24(1,0.6,0)
    @test convert(ARGB32, RGB24(1,0.6,0)) === ARGB32(1,0.6,0,1)
    @test convert(ARGB32, RGB24(1,0.6,0), 0.2) === ARGB32(1,0.6,0,0.2)
    @test convert(RGB24, ARGB32(1,0.6,0,0.8)) === RGB24(1,0.6,0)
    @test convert(ARGB32, ARGB32(1,0.6,0,0.8)) === ARGB32(1,0.6,0,0.8)
end

@testset "conversions from gray to gray" begin
    @testset "Gray conversions" begin
        @test convert(Gray, Gray{Float64}(0.4)) === Gray{Float64}(0.4)
        @test convert(Gray{N0f8}, Gray{Float64}(0.4)) === Gray{N0f8}(0.4)
        @test convert(Gray, Gray24(0.4)) === Gray{N0f8}(0.4)
        @test convert(Gray24, Gray(0.4)) === Gray24(0.4)
        @test convert(Gray, AGray32(0.4,0.8)) === Gray{N0f8}(0.4)
        @test convert(AGray32, Gray(0.4)) === AGray32(0.4)
        @test convert(AGray32, Gray(0.4), 0.2) === AGray32(0.4, 0.2)
    end
    @testset "$C conversions" for C in (AGray, GrayA)
        @test convert(C, C{Float64}(0.4,0.8)) === C{Float64}(0.4,0.8)
        @test convert(C{N0f8}, C{Float64}(0.4,0.8)) === C{N0f8}(0.4,0.8)
        @test convert(C, Gray24(0.4)) === C{N0f8}(0.4,1)
        @test convert(C, Gray24(0.4), 0.2) === C{N0f8}(0.4,0.2)
        @test convert(Gray24, C(0.4,0.8)) === Gray24(0.4)
        @test convert(C, AGray32(0.4,0.8)) === C{N0f8}(0.4,0.8)
        @test convert(AGray32, C(0.4,0.8)) === AGray32(0.4,0.8)
    end
    @test convert(Gray24, Gray24(0.4)) === Gray24(0.4)
    @test convert(AGray32, Gray24(0.4)) === AGray32(0.4,1)
    @test convert(AGray32, Gray24(0.4), 0.2) === AGray32(0.4,0.2)
    @test convert(Gray24, AGray32(0.4,0.8)) === Gray24(0.4)
    @test convert(AGray32, AGray32(0.4,0.8)) === AGray32(0.4,0.8)
end

@testset "conversions from hsv to hsv" begin
    @testset "HSV conversions" begin
        @test convert(HSV, HSV{Float64}(100,0.4,0.6)) === HSV{Float64}(100,0.4,0.6)
        @test convert(HSV{Float32}, HSV{Float64}(100,0.4,0.6)) === HSV{Float32}(100,0.4,0.6)
        @test convert(HSV, HSVA{Float64}(100,0.4,0.6,0.8)) === HSV{Float64}(100,0.4,0.6)
        @test convert(HSV, AHSV{Float32}(100,0.4,0.6,0.8)) === HSV{Float32}(100,0.4,0.6)
    end
    @testset "$C conversions" for C in (AHSV, HSVA)
        @test convert(C, HSVA{Float64}(100,0.4,0.6,0.8)) === C{Float64}(100,0.4,0.6,0.8)
        @test convert(C, AHSV{Float32}(100,0.4,0.6,0.8)) === C{Float32}(100,0.4,0.6,0.8)
        @test convert(C{Float32}, HSVA{Float64}(100,0.4,0.6,0.8)) === C{Float32}(100,0.4,0.6,0.8)
        @test convert(C{Float32}, AHSV{Float32}(100,0.4,0.6,0.8)) === C{Float32}(100,0.4,0.6,0.8)
        @test convert(C, HSV{Float64}(100,0.4,0.6)) === C{Float64}(100,0.4,0.6,1)
        @test convert(C, HSV{Float32}(100,0.4,0.6), 0.2) === C{Float32}(100,0.4,0.6,0.2)
    end
end

@testset "conversions from gray to rgb" begin
    Crgb = filter(T -> T <: AbstractRGB, ColorTypes.parametric3)
    Ctransparent = unique(vcat(coloralpha.(Crgb), alphacolor.(Crgb)))
    @testset "$C conversions" for C in Crgb
        @test convert(C,  Gray{N0f8}(0.4)    ) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C, GrayA{N0f8}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C, AGray{N0f8}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C{N0f8},  Gray{N0f8}(0.4)    ) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C{N0f8}, GrayA{N0f8}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C{N0f8}, AGray{N0f8}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C{Float32},  Gray{N0f8}(0.4)    ) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8)
        @test convert(C{Float32}, GrayA{N0f8}(0.4,0.8)) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8)
        @test convert(C{Float32}, AGray{N0f8}(0.4,0.8)) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8)
        @test convert(C{N0f8},  Gray{Float32}(0.4)    ) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C{N0f8}, GrayA{Float32}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C{N0f8}, AGray{Float32}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C,  Gray24(0.4)    ) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C, AGray32(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C{N0f8},  Gray24(0.4)    ) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C{N0f8}, AGray32(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4)
        @test convert(C{Float32},  Gray24(0.4)    ) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8)
        @test convert(C{Float32}, AGray32(0.4,0.8)) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8)
    end
    @testset "$C conversions" for C in Ctransparent
        @test convert(C,  Gray{N0f8}(0.4)    ) === C{N0f8}(0.4,0.4,0.4,1)
        @test convert(C,  Gray{N0f8}(0.4),0.2) === C{N0f8}(0.4,0.4,0.4,0.2)
        @test convert(C, GrayA{N0f8}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4,0.8)
        @test convert(C, AGray{N0f8}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4,0.8)
        @test convert(C{N0f8},  Gray{N0f8}(0.4)    ) === C{N0f8}(0.4,0.4,0.4,1)
        @test convert(C{N0f8},  Gray{N0f8}(0.4),0.2) === C{N0f8}(0.4,0.4,0.4,0.2)
        @test convert(C{N0f8}, GrayA{N0f8}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4,0.8)
        @test convert(C{N0f8}, AGray{N0f8}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4,0.8)
        @test convert(C{Float32},  Gray{N0f8}(0.4)    ) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8,1)
        @test convert(C{Float32},  Gray{N0f8}(0.4),0.2) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8,0.2)
        @test convert(C{Float32}, GrayA{N0f8}(0.4,0.8)) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8,0.8N0f8)
        @test convert(C{Float32}, AGray{N0f8}(0.4,0.8)) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8,0.8N0f8)
        @test convert(C{N0f8},  Gray{Float32}(0.4)    ) === C{N0f8}(0.4,0.4,0.4,1)
        @test convert(C{N0f8},  Gray{Float32}(0.4),0.2) === C{N0f8}(0.4,0.4,0.4,0.2)
        @test convert(C{N0f8}, GrayA{Float32}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4,0.8)
        @test convert(C{N0f8}, AGray{Float32}(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4,0.8)
        @test convert(C,  Gray24(0.4)    ) === C{N0f8}(0.4,0.4,0.4,1)
        @test convert(C,  Gray24(0.4),0.2) === C{N0f8}(0.4,0.4,0.4,0.2)
        @test convert(C, AGray32(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4,0.8)
        @test convert(C{N0f8},  Gray24(0.4)    ) === C{N0f8}(0.4,0.4,0.4,1)
        @test convert(C{N0f8},  Gray24(0.4),0.2) === C{N0f8}(0.4,0.4,0.4,0.2)
        @test convert(C{N0f8}, AGray32(0.4,0.8)) === C{N0f8}(0.4,0.4,0.4,0.8)
        @test convert(C{Float32},  Gray24(0.4)    ) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8,1)
        @test convert(C{Float32},  Gray24(0.4),0.2) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8,0.2)
        @test convert(C{Float32}, AGray32(0.4,0.8)) === C{Float32}(0.4N0f8,0.4N0f8,0.4N0f8,0.8N0f8)
    end
    @testset "RGB24 conversions" begin
        @test convert(RGB24,  Gray{N0f8}(0.4)    ) === RGB24(0.4,0.4,0.4)
        @test convert(RGB24, GrayA{N0f8}(0.4,0.8)) === RGB24(0.4,0.4,0.4)
        @test convert(RGB24, AGray{Float32}(0.4,0.8)) === RGB24(0.4,0.4,0.4)
        @test convert(RGB24,  Gray24(0.4)    ) === RGB24(0.4,0.4,0.4)
        @test convert(RGB24, AGray32(0.4,0.8)) === RGB24(0.4,0.4,0.4)
    end
    @testset "ARGB32 conversions" begin
        @test convert(ARGB32,  Gray{N0f8}(0.4)    ) === ARGB32(0.4,0.4,0.4,1)
        @test convert(ARGB32,  Gray{N0f8}(0.4),0.2) === ARGB32(0.4,0.4,0.4,0.2)
        @test convert(ARGB32, GrayA{N0f8}(0.4,0.8)) === ARGB32(0.4,0.4,0.4,0.8)
        @test convert(ARGB32, AGray{Float32}(0.4,0.8)) === ARGB32(0.4,0.4,0.4,0.8)
        @test convert(ARGB32,  Gray24(0.4)    ) === ARGB32(0.4,0.4,0.4,1)
        @test convert(ARGB32,  Gray24(0.4),0.2) === ARGB32(0.4,0.4,0.4,0.2)
        @test convert(ARGB32, AGray32(0.4,0.8)) === ARGB32(0.4,0.4,0.4,0.8)
    end
end

@testset "conversions between different spaces" begin
    @test_throws ErrorException convert(HSV, RGB(1,0,1))
    @test_throws ErrorException convert(AHSV, RGB(1,0,1), 0.5)
end

@testset "alphacolor/coloralpha for instances" begin
    Cp3 = ColorTypes.parametric3
    @testset "alphacolor/coloralpha: $C" for C in Cp3
        cf64, cf32 = C{Float64}(1, 0.6, 0), C{Float32}(1, 0.6, 0)
        for f in (alphacolor, coloralpha)
            A = f(C)
            @test f(cf64) === A{Float64}(1, 0.6, 0, 1)
            @test f(cf64, 0.8) === A{Float64}(1, 0.6, 0, 0.8)
            @test f(cf32, 0.8) === A{Float32}(1, 0.6, 0, 0.8)
            @test f(cf32, 0.8N0f8) === A{Float32}(1, 0.6, 0, 0.8N0f8)
        end
    end
    Ct3 = unique(vcat(coloralpha.(Cp3), alphacolor.(Cp3)))
    @testset "alphacolor/coloralpha: $C" for C in Ct3
        cf64, cf32 = C{Float64}(1, 0.6, 0, 0.4), C{Float32}(1, 0.6, 0, 0.4)
        for f in (alphacolor, coloralpha)
            A = f(C)
            @test f(cf64) === A{Float64}(1, 0.6, 0, 0.4)
            @test f(cf64, 0.8) === A{Float64}(1, 0.6, 0, 0.8)
            @test f(cf32, 0.8) === A{Float32}(1, 0.6, 0, 0.8)
            @test f(cf32, 0.8N0f8) === A{Float32}(1, 0.6, 0, 0.8N0f8)
        end
    end
    @testset "alphacolor/coloralpha: $C" for C in (Gray, AGray, GrayA)
        cf64 = C === Gray ? Gray(0.6)   : C{Float64}(0.6, 0.4)
        cf32 = C === Gray ? Gray(0.6f0) : C{Float32}(0.6, 0.4)
        for f in (alphacolor, coloralpha)
            A = f(C)
            @test f(cf64) === A{Float64}(0.6, C === Gray ? 1 : 0.4)
            @test f(cf64, 0.8) === A{Float64}(0.6, 0.8)
            @test f(cf32, 0.8) === A{Float32}(0.6, 0.8)
            @test f(cf32, 0.8N0f8) === A{Float32}(0.6, 0.8N0f8)
        end
    end

    @test alphacolor(RGB{N0f8}(1,0.6,0), 0.8) === ARGB{N0f8}(1,0.6,0,0.8)
    @test coloralpha(RGB{N0f8}(1,0.6,0), 0.8) === RGBA{N0f8}(1,0.6,0,0.8)

    @test alphacolor(RGB24(1,0.6,0)) === ARGB32(1,0.6,0, 1)
    @test alphacolor(RGB24(1,0.6,0), 0.8) === ARGB32(1,0.6,0, 0.8)
    @test_throws MethodError coloralpha(RGB24(1,0.6,0))
    @test_throws MethodError coloralpha(RGB24(1,0.6,0), 0.8)

    @test alphacolor(ARGB32(1,0.6,0)) === ARGB32(1,0.6,0, 1)
    @test alphacolor(ARGB32(1,0.6,0), 0.8) === ARGB32(1,0.6,0, 0.8)
    @test_throws MethodError coloralpha(ARGB32(1,0.6,0))
    @test_throws MethodError coloralpha(ARGB32(1,0.6,0), 0.8)

    @test alphacolor(Gray24(0.6)) === AGray32(0.6, 1)
    @test alphacolor(Gray24(0.6), 0.8) === AGray32(0.6, 0.8)
    @test_throws MethodError coloralpha(Gray24(0.6))
    @test_throws MethodError coloralpha(Gray24(0.6), 0.8)

    @test alphacolor(AGray32(0.6)) === AGray32(0.6, 1)
    @test alphacolor(AGray32(0.6), 0.8) === AGray32(0.6, 0.8)
    @test_throws MethodError coloralpha(AGray32(0.6))
    @test_throws MethodError coloralpha(AGray32(0.6), 0.8)
end

### Prevent ambiguous definitions

# Certain types, like Gray24, reinterpret a UInt32 as having a
# particular color meaning. The problem with defining `convert`
# methods is that a UInt32 has a value, e.g., 0 = black and 1 = white.
# Users who want to interpret a UInt32 as a bit pattern should
# explicitly use `reinterpret`.
@testset "bit pattern ambiguities" begin
    @test_throws MethodError convert(UInt32, RGB24(1,1,1))
    @test_throws MethodError convert(UInt32, ARGB32(1,1,1,0))
    @test convert(UInt32, Gray24(1)) === UInt32(1)
    @test_throws InexactError convert(UInt32, Gray24(0.5))
    @test_throws MethodError convert(UInt32, AGray32(1,0))
    @test !(RGB24(1,1,1) == 0x00ffffff)
    @test !(ARGB32(1,1,1,0) == 0x00ffffff)
    @test Gray24(1) == 1
    @test !(Gray24(1) == 0x00ffffff)
    @test !(AGray32(1,0) == 0x00ffffff)
    @test_throws ArgumentError RGB24(0x00ffffff)
    @test_throws ArgumentError ARGB32(0x00ffffff)
    @test_throws ArgumentError Gray24(0x00ffffff)
    @test_throws ArgumentError AGray32(0x00ffffff)
    @test_throws ArgumentError RGB24[0x00000000,0x00808080]
    @test_throws ArgumentError RGB24[0x00000000,0x00808080,0x00ffffff]
    @test_throws ArgumentError RGB24[0x00000000,0x00808080,0x00ffffff,0x000000ff]
end


text:
# Bogumił Kamiński, 2021

# Codes for chapter 3

# Code for section 3.1

methods(cd)

sum isa Function

typeof(sum)
typeof(sum) == Function

supertype(typeof(sum))

function print_supertypes(T)
    println(T)
    T == Any || print_supertypes(supertype(T))
    return nothing
end
print_supertypes(Int64)

function print_subtypes(T, indent_level=0)
    println(" " ^ indent_level, T)
    for S in subtypes(T)
        print_subtypes(S, indent_level + 2)
    end
    return nothing
end
print_subtypes(Integer)

print_supertypes(typeof([1.0, 2.0, 3.0]))
print_supertypes(typeof(1:3))

AbstractVector

typejoin(typeof([1.0, 2.0, 3.0]), typeof(1:3))

# Code for section 3.2

fun(x) = println("unsupported type")
fun(x::Number) = println("a number was passed")
fun(x::Float64) = println("a Float64 value")
methods(fun)

fun("hello!")
fun(1)
fun(1.0)

bar(x, y) = "no numbers passed"
bar(x::Number, y) = "first argument is a number"
bar(x, y::Number) = "second argument is a number"
bar("hello", "world")
bar(1, "world")
bar("hello", 2)
bar(1, 2)

bar(x::Number, y::Number) = "both arguments are numbers"
bar(1, 2)
methods(bar)

function winsorized_mean(x::AbstractVector, k::Integer)
    k >= 0 || throw(ArgumentError("k must be non-negative"))
    length(x) > 2 * k || throw(ArgumentError("k is too large"))
    y = sort!(collect(x))
    for i in 1:k
        y[i] = y[k + 1]
        y[end - i + 1] = y[end - k]
    end
    return sum(y) / length(y)
end

winsorized_mean([8, 3, 1, 5, 7], 1)
winsorized_mean(1:10, 2)
winsorized_mean(1:10, "a")
winsorized_mean(10, 1)

winsorized_mean(1:10, -1)
winsorized_mean(1:10, 5)

# Code for section 3.3

module ExampleModule

function example()
    println("Hello")
end

end # ExampleModule

import Statistics
x = [1, 2, 3]
mean(x)
Statistics.mean(x)

using Statistics
mean(x)

# start a fresh Julia session before running this code
mean = 1
using Statistics
mean

# start a fresh Julia session before running this code
using Statistics
mean([1, 2, 3])
mean = 1

# start a fresh Julia session before running this code
using Statistics
mean = 1
mean([1, 2, 3])

# start a fresh Julia session before running this code
using Statistics
using StatsBase

# - change to help mode by pressing `?` key
# - type "winsor" and press Enter

mean(winsor([8, 3, 1, 5, 7], count=1))

# Code for section 3.4

@time 1 + 2

@time(1 + 2)

@assert 1 == 2 "1 is not equal 2"
@assert(1 == 2, "1 is not equal 2")

@macroexpand @assert(1 == 2, "1 is not equal 2")

@macroexpand @time 1 + 2

# before running these codes
# define the winsorized_mean function using the code from section 3.1

using BenchmarkTools
x = rand(10^6);
@benchmark winsorized_mean($x, 10^5)
using Statistics, StatsBase
@benchmark mean(winsor($x; count=10^5))

@edit winsor(x, count=10^5)

ext: jl

max_stars_repo_name: bkamins/JuliaForDataAnalysis

max_issues_repo_name: bkamins/JuliaForDataAnalysis

max_forks_repo_name: bkamins/JuliaForDataAnalysis


text:
using C2Julia
using Test

include("if.jl")
include("loop.jl")
include("literal.jl")
include("operator.jl")
include("goto.jl")
include("switch.jl")
include("call.jl")
include("array.jl")


text:
for N in [Float64, Rational{Int}, Float32]
    # random ball
    rand(BallInf)

    # 1D BallInf
    b = BallInf(N[0], N(1))
    # Test Dimension
    @test dim(b) == 1
    # Test Support Vector
    d = N[1]
    @test σ(d, b) == N[1]
    d = N[-1]
    @test σ(d, b) == N[-1]

    # 2D BallInf
    b = BallInf(N[0, 0], N(1))
    # Test Dimension
    @test dim(b) == 2
    # Test Support Vector
    d = N[1, 1]
    @test σ(d, b) == N[1, 1]
    d = N[-1, 1]
    @test σ(d, b) == N[-1, 1]
    d = N[-1, -1]
    @test σ(d, b) == N[-1, -1]
    d = N[1, -1]
    @test σ(d, b) == N[1, -1]

    # 2D BallInf not 0-centered
    b = BallInf(N[1, 2], N(1))
    # Test Dimension
    @test dim(b) == 2
    # Test Support Vector
    d = N[1, 1]
    @test σ(d, b) == N[2, 3]
    d = N[-1, 1]
    @test σ(d, b) == N[0, 3]
    d = N[-1, -1]
    @test σ(d, b) == N[0, 1]
    d = N[0, -1]
    @test σ(d, b) == N[2, 1]

    # 2D BallInf radius =/= 1
    b = BallInf(N[0, 0], N(2))
    # Test Dimension
    @test dim(b) == 2
    # Test Support Vector
    d = N[1, 1]
    @test σ(d, b) == N[2, 2]
    d = N[-1, 1]
    @test σ(d, b) == N[-2, 2]
    d = N[-1, -1]
    @test σ(d, b) == N[-2, -2]
    d = N[1, -1]
    @test σ(d, b) == N[2, -2]

    # boundedness
    @test isbounded(b)

    # isempty
    @test !isempty(b)

    # membership
    b = BallInf(N[1, 1], N(1))
    @test !∈(N[0.5, -0.5], b)
    @test ∈(N[0.5, 1.5], b)

    # an_element function
    b = BallInf(N[1, 2], N(3))
    @test an_element(b) ∈ b

    # check that vertices_list for zero radius doesn't repeat vertices
    b = BallInf(N[1, 2], N(0))
    vl = vertices_list(b)
    @test vl == [center(b)]

    # high and low
    b = BallInf(N[1, 2], N(1))
    @test high(b) == N[2, 3]
    @test low(b) == N[0, 1]

    # isflat
    @test !isflat(BallInf(N[1, 1], N(1))) && isflat(BallInf(N[1, 1], N(0)))

    # split
    b = BallInf(N[3, 3], N(1))
    @test split(b, [1, 1]) == [Hyperrectangle(N[3, 3], N[1, 1])]
    @test ispermutation(split(b, [2, 1]),
        [Hyperrectangle(N[2.5, 3], N[0.5, 1]),
         Hyperrectangle(N[3.5, 3], N[0.5, 1])])

    # translation
    b = BallInf(N[1, 2], N(1))
    @test translate(b, N[1, 2]) == BallInf(N[2, 4], N(1))
end


text:
using Statistics
using Oceananigans.Architectures

using OffsetArrays: OffsetArray

import Base: getindex, size, show, minimum, maximum
import Statistics: mean

import Oceananigans.Fields: AbstractField, AbstractDataField, AbstractReducedField, Field, ReducedField, minimum, maximum, mean, location
import Oceananigans.Grids: new_data
import Oceananigans.BoundaryConditions: FieldBoundaryConditions

struct CubedSphereFaces{E, F}
    faces :: F
end

@inline Base.getindex(f::CubedSphereFaces, i::Int) = @inbounds f.faces[i]

#####
##### Dispatch the world
#####

const CubedSphereData = CubedSphereFaces{<:OffsetArray}

# Flavors of CubedSphereField
const CubedSphereField = Field{X, Y, Z, A, <:CubedSphereData} where {X, Y, Z, A}
const CubedSphereReducedField = ReducedField{X, Y, Z, A, <:CubedSphereData} where {X, Y, Z, A}
const CubedSphereAbstractField = AbstractField{X, Y, Z, A, <:ConformalCubedSphereGrid} where {X, Y, Z, A}
const CubedSphereAbstractDataField = AbstractDataField{X, Y, Z, A, <:ConformalCubedSphereGrid} where {X, Y, Z, A}
const CubedSphereAbstractReducedField = AbstractReducedField{X, Y, Z, A, D, <:ConformalCubedSphereFaceGrid} where {X, Y, Z, A, D}

const AbstractCubedSphereField = Union{CubedSphereAbstractField,
                                       CubedSphereAbstractDataField,
                                       CubedSphereAbstractReducedField,
                                       CubedSphereField}

# Just a single face
const CubedSphereFaceField = AbstractField{X, Y, Z, A, <:ConformalCubedSphereFaceGrid} where {X, Y, Z, A}

# There must be a way to dispatch in one function without ambiguity with `new_data.jl`...

function new_data(FT, arch::AbstractCPUArchitecture, grid::ConformalCubedSphereGrid, (X, Y, Z))
    faces = Tuple(new_data(FT, arch, face_grid, (X, Y, Z)) for face_grid in grid.faces)
    return CubedSphereFaces{typeof(faces[1]), typeof(faces)}(faces)
end

function new_data(FT, arch::AbstractGPUArchitecture, grid::ConformalCubedSphereGrid, (X, Y, Z))
    faces = Tuple(new_data(FT, arch, face_grid, (X, Y, Z)) for face_grid in grid.faces)
    return CubedSphereFaces{typeof(faces[1]), typeof(faces)}(faces)
end

function FieldBoundaryConditions(grid::ConformalCubedSphereGrid, (X, Y, Z); user_defined_bcs...)

    faces = Tuple(
        inject_cubed_sphere_exchange_boundary_conditions(
            FieldBoundaryConditions(face_grid, (X, Y, Z); user_defined_bcs...),
            face_index,
            grid.face_connectivity
        )
        for (face_index, face_grid) in enumerate(grid.faces)
    )

    return CubedSphereFaces{typeof(faces[1]), typeof(faces)}(faces)
end

#####
##### Utils
#####

@inline function interior(field::AbstractCubedSphereField)
    faces = Tuple(interior(face_field_face) for face_field in faces(field))
    return CubedSphereFaces(faces)
end

Base.size(data::CubedSphereData) = (size(data.faces[1])..., length(data.faces))

@inline function get_face(field::AbstractCubedSphereField, face_index)
    X, Y, Z = location(field)

    # Should we define a new lower-level constructor for Field that doesn't call validate_field_data?
    return Field{X, Y, Z}(get_face(field.data, face_index),
                          field.architecture,
                          get_face(field.grid, face_index),
                          get_face(field.boundary_conditions, face_index))
end

@inline function get_face(reduced_field::CubedSphereAbstractReducedField, face_index)
    X, Y, Z = location(reduced_field)

    return ReducedField{X, Y, Z}(get_face(reduced_field.data, face_index),
                                 reduced_field.architecture,
                                 get_face(reduced_field.grid, face_index),
                                 reduced_field.dims,
                                 get_face(reduced_field.boundary_conditions, face_index))
end

faces(field::AbstractCubedSphereField) = Tuple(get_face(field, face_index) for face_index in 1:length(field.data.faces))

minimum(field::AbstractCubedSphereField; dims=:) = minimum(minimum(face_field; dims) for face_field in faces(field))
maximum(field::AbstractCubedSphereField; dims=:) = maximum(maximum(face_field; dims) for face_field in faces(field))
mean(field::AbstractCubedSphereField; dims=:) = mean(mean(face_field; dims) for face_field in faces(field))

minimum(f, field::AbstractCubedSphereField; dims=:) = minimum(minimum(f, face_field; dims) for face_field in faces(field))
maximum(f, field::AbstractCubedSphereField; dims=:) = maximum(maximum(f, face_field; dims) for face_field in faces(field))
mean(f, field::AbstractCubedSphereField; dims=:) = mean(mean(f, face_field; dims) for face_field in faces(field))

λnodes(field::CubedSphereFaceField{LX, LY, LZ}) where {LX, LY, LZ} = λnodes(LX(), LY(), LZ(), field.grid)
φnodes(field::CubedSphereFaceField{LX, LY, LZ}) where {LX, LY, LZ} = φnodes(LX(), LY(), LZ(), field.grid)


text:
using JSON
using HTTP

function read_data(filename::String)
    f = open(f->read(f, String), filename)
    return f
end

function parse_json(data::String)
    return JSON.parse(data)
end

function write_data(filename::String, data)
    f = open(string(filename), "w")
    JSON.Writer.print(f, data, 2)
    close(f)
end

function ipynb_to_colab(notebook_name::String)
    # Reading normal ipynb notebook
    input_filename = notebook_name
    normal_data = read_data(input_filename)
    normal_json = parse_json(normal_data)

    # Reading the configuration notebook
    colab_json = parse_json(String(HTTP.get("https://raw.githubusercontent.com/Chandu-4444/Colab.jl/main/src/assets/Config_Notebook.json").body))
    # Updataing metadata
    normal_json["metadata"] = colab_json["metadata"]
    # Adding the configuration cell at the top
    pushfirst!(normal_json["cells"], colab_json["cells"][1])
    # output filename would be input_filename + "_colab.ipynb"
    output_filename = string(string(split(input_filename, ".")[1]), "_colab", ".ipynb")

    write_data(output_filename, normal_json)
end

export ipynb_to_colab


text:
#=
BINARYBUILDER_RUNNER=privileged julia build_tarballs.jl --verbose --debug
=#

using BinaryBuilder
using Pkg

version = v"2.3.0" # libIGL version, see below:

sources = [
	DirectorySource("./iglwrap"),
	# 2.3.0 stable release:
	GitSource("https://github.com/libigl/libigl.git",
		"e60423e28c86b6aa2a3f6eb0112e8fd881f96777"),
]

script = raw"""
cd $WORKSPACE/srcdir
mkdir -p build
cd build
cmake \
    -DCMAKE_INSTALL_PREFIX=${prefix} \
    -DCMAKE_TOOLCHAIN_FILE=${CMAKE_TARGET_TOOLCHAIN} \
    -DCMAKE_MODULE_PATH=${WORKSPACE}/srcdir/libigl/cmake\; \
    `# We can't run try_run in cross-compilation mode, pass the exit code and stdout of the program (the value of __cplusplus macro)` \
    -DCGAL_test_cpp_version_RUN_RES=0 \
    -DCGAL_test_cpp_version_RUN_RES__TRYRUN_OUTPUT="$(c++ -xc++ - -E -dM < /dev/null | grep -oP '__cplusplus \K.*')" \
    ..
make -j${nproc}
make install
install_license /usr/share/licenses/GPL3
"""

products = [
	LibraryProduct("libiglwrap", :libiglwrap;
		dlopen_flags=[:RTLD_NOW,:RTLD_LOCAL])
]

platforms = [
	# 2021-10-30: LibIGL won't compile on at least MacOS right now, but
	# works on the following platforms:
	Platform("x86_64", "linux"),
]
# platforms = supported_platforms()

platforms = expand_cxxstring_abis(platforms)

dependencies = [
    Dependency("boost_jll", compat="~1.71"),
    Dependency("GMP_jll"),
    Dependency("MPFR_jll"),
    Dependency("OpenBLAS_jll"),
]

build_tarballs(ARGS, "IGLWrap", version,
    sources,
    script,
    platforms,
    products,
    dependencies,
)

max_stars_repo_name: sharanry/Yggdrasil

max_issues_repo_name: sharanry/Yggdrasil

max_forks_repo_name: sharanry/Yggdrasil


text:
subtract(x, y; kwargs...) = -(x, y; kwargs...)
subtract(x::Vector, y::Vector; kwargs...) = [subtract(x[i], y[i]; kwargs...) for i in 1:length(x)]

# Simple gradient descent to minimize the function `f`
# given the gradient `gradf`.
function minimize(f, gradf, x; nsteps, gamma, print_frequency=10, kwargs...)
  for n in 1:nsteps
    x = subtract(x, gamma * gradf(x); kwargs...)
    if n % print_frequency == 0
      println("Step = $(n), f(x) = $(f(x))")
    end
  end
  return x
end


text:
function summary(
    decisionMat::DataFrame,
    weights::Array{Float64,1},
    fns::Array{Function,1},
    methods::Array{Symbol,1})

    nmethods = length(methods)
    nalternatives, _ = size(decisionMat)

    resultdf = DataFrame()

    check = " ✅ "

    if :topsis in methods
        topresult = topsis(decisionMat, weights, fns)
        resultdf[:,:topsis] = map(x -> if topresult.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :electre in methods
        # electre best index is a tuple
        result = electre(decisionMat, weights, fns)
        resultdf[:,:electre] = map(x -> if x in result.bestIndex check else " " end, 1:nalternatives)
    end

    if :cocoso in methods
        result = cocoso(decisionMat, weights, fns)
        resultdf[:,:cocoso] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :copras in methods
        result = copras(decisionMat, weights, fns)
        resultdf[:,:copras] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :moora in methods
        result = moora(decisionMat, weights, fns)
        resultdf[:,:moora] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :vikor in methods
        result = vikor(decisionMat, weights, fns)
        resultdf[:,:vikor] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :grey in methods
        result = grey(decisionMat, weights, fns)
        resultdf[:,:grey] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :aras in methods
        result = aras(decisionMat, weights, fns)
        resultdf[:,:aras] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :saw in methods
        result = saw(decisionMat, weights, fns)
        resultdf[:,:saw] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :wpm in methods
        result = wpm(decisionMat, weights, fns)
        resultdf[:,:wpm] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :waspas in methods
        result = waspas(decisionMat, weights, fns)
        resultdf[:,:waspas] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :edas in methods
        result = edas(decisionMat, weights, fns)
        resultdf[:,:edas] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :marcos in methods
        result = marcos(decisionMat, weights, fns)
        resultdf[:,:marcos] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :mabac in methods
        result = mabac(decisionMat, weights, fns)
        resultdf[:,:mabac] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :mairca in methods
        result = mairca(decisionMat, weights, fns)
        resultdf[:,:mairca] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :copras in methods
        result = copras(decisionMat, weights, fns)
        resultdf[:,:copras] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :cocoso in methods
        result = cocoso(decisionMat, weights, fns)
        resultdf[:,:cocoso] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    if :critic in methods
        result = critic(decisionMat, fns)
        resultdf[:,:critic] = map(x -> if result.bestIndex == x check else " " end, 1:nalternatives)
    end

    return resultdf

end

max_stars_repo_name: bahadirfyildirim/JMcDM

max_issues_repo_name: bahadirfyildirim/JMcDM

max_forks_repo_name: bahadirfyildirim/JMcDM


text:
# Use baremodule to shave off a few KB from the serialized `.ji` file
baremodule Xorg_xcb_util_keysyms_jll
using Base
using Base: UUID
import JLLWrappers

JLLWrappers.@generate_main_file_header("Xorg_xcb_util_keysyms")
JLLWrappers.@generate_main_file("Xorg_xcb_util_keysyms", UUID("975044d2-76e6-5fbe-bf08-97ce7c6574c7"))
end  # module Xorg_xcb_util_keysyms_jll


text:
# use Pose2 and test that the manifold products are working
using Statistics
using Test
using RoME, Distributions
# using KernelDensityEstimate

# using Gadfly
# using RoMEPlotting

using ApproxManifoldProducts
# const AMP = ApproxManifoldProducts

##

@testset "Testing hand constructed product of SE(2) equivalent..." begin

## Reuse variables

pt = Pose2()

##

# Pose densities on SE3 equivalent
pts1a = 0.1*randn(1,100)
pts1b = 0.1*randn(1,100)
pts1c = TransformUtils.wrapRad.( 0.1*randn(1,100) )
p = manikde!([pts1a;pts1b;pts1c], Pose2().manifolds )

#

pts2a = 3.0*randn(1,100).+4.0
pts2b = 3.0*randn(1,100)
pts2c = TransformUtils.wrapRad.(0.15*randn(1,100).+0.7pi)
q = manikde!([pts2a;pts2b;pts2c], Pose2().manifolds  )

pts3a = 3.0*randn(1,100).-4.0
pts3b = 3.0*randn(1,100)
pts3c = TransformUtils.wrapRad.(0.15*randn(1,100).-0.7pi)
r = manikde!([pts3a;pts3b;pts3c], Pose2().manifolds  )

# pl = plotPose(pt, [q; r], levels=1)

qr = manifoldProduct([q;r], pt.manifolds, Niter=3)

# pl = plotPose(pt, [q; r; qr], levels=2, c=["cyan";"cyan";"red"])

##

# Pose densities on SE3 equivalent
# pts1a = 0.1*randn(1,100)
# pts1b = 0.1*randn(1,100)
# pts1c = TransformUtils.wrapRad.( 0.1*randn(1,100) )
# p = manikde!([pts1a;pts1b;pts1c], Pose2().manifolds )

R = [1 1; -1 1]./sqrt(2)
I2 = [16.0 0; 0 0.5]
mvn = MvNormal([0.0;0.0],  R*I2*(R'))
pts1 = rand(mvn, 100)
# Gadfly.plot(x=pts1[1,:],y=pts1[2,:],Geom.hexbin )

pts2a = pts1[1:1,:].+5.0
pts2b = pts1[2:2,:].+5.0
pts2c = TransformUtils.wrapRad.(0.25*randn(1,100).+pi/2)
q = manikde!([pts2a;pts2b;pts2c], Pose2().manifolds  )

R = [1 -1; 1 1]./sqrt(2)
I2 = [16.0 0; 0 0.5]
mvn = MvNormal([0.0;0.0],  R*I2*(R'))
pts2 = rand(mvn, 100)
# Gadfly.plot(x=pts2[1,:],y=pts2[2,:],Geom.hexbin )

pts3a = pts2[1:1,:]
pts3b = pts2[2:2,:]
pts3c = TransformUtils.wrapRad.(0.25*randn(1,100).-pi/2)
r = manikde!([pts3a;pts3b;pts3c], Pose2().manifolds  )

##

qr = manifoldProduct([q;r], pt.manifolds, Niter=8)

# pl = plotPose(pt, [q; r; qr], levels=3, c=["cyan";"cyan";"red"])

##

# Pose densities on SE3 equivalent
pts1a = 0.5*randn(1,100)
pts1b = 0.5*randn(1,100)
pts1c = TransformUtils.wrapRad.( 0.1*randn(1,100) )
p = manikde!([pts1a;pts1b;pts1c], Pose2().manifolds )

pts2a = 0.5*randn(1,100)
pts2b = 1.0*randn(1,100)
pts2c = TransformUtils.wrapRad.(0.15*randn(1,100).+2pi/3)
q = manikde!([pts2a;pts2b;pts2c], Pose2().manifolds  )

pts3a = 1.0*randn(1,100)
pts3b = 0.5*randn(1,100)
pts3c = TransformUtils.wrapRad.(0.15*randn(1,100).-2pi/3)
r = manikde!([pts3a;pts3b;pts3c], Pose2().manifolds  )

pqr = manifoldProduct([p;q;r], pt.manifolds)

# pl = plotPose(pt, [p; q; r; pqr], levels=1, c=["cyan";"cyan";"cyan";"red"])

end # testset

## Save the latest plot to file

# pl |> SVG("/tmp/test.svg",12cm,10cm)
# @async run(`eog /tmp/test.svg`)
#
#
# pl |> PNG("/tmp/test.png",12cm,10cm)
# @async run(`eog /tmp/test.png`)

## repeat one of the examples but in a factor graph

@testset "Factor graph based test of SE(2) equivalent using only Priors..." begin

N = 100

#test as priors on one node

pts2a = 3.0*randn(1,N)
pts2b = 3.0*randn(1,N)
pts2c = TransformUtils.wrapRad.(0.15*randn(1,N).+0.9pi)
q = manikde!([pts2a;pts2b;pts2c], Pose2().manifolds  )

pts3a = 3.0*randn(1,N).+4.0
pts3b = 3.0*randn(1,N).+4.0
pts3c = TransformUtils.wrapRad.(0.15*randn(1,N).-0.9pi)
r = manikde!([pts3a;pts3b;pts3c], Pose2().manifolds  )

fg = initfg()

addVariable!(fg, :x1, Pose2)

addFactor!(fg, [:x1], Prior(q))
addFactor!(fg, [:x1], Prior(r))

# writeGraphPdf(fg, show=true)

stuff = IIF.localProduct(fg, :x1)

@test 0.90*N < sum( -10 .< getPoints(stuff[1])[1,:] .< 15)
@test 0.90*N < sum( -10 .< getPoints(stuff[1])[2,:] .< 15)

@test 0.90*N < sum(2.7 .< abs.(getPoints(stuff[1])[3,:]) .< 1.01*pi)

##
# plotPose(Pose2(), [getVertKDE(fg, :x1)])
#
# plotPose(Pose2(), [stuff[2];stuff[1]], levels=2, c=["cyan";"cyan";"red"])

##

end

@testset "Factor graph based test of SE(2) equivalent using Priors and Conditional Likelihoods..." begin

N = 100

@warn "not implemented yet"

end

##


text:
"""
    substitute!(dest::Sym, x::Sym, pairs...; strict=false)

Like `substitute(x, pairs...)` but overwrites `dest` with the result.

"""
function substitute!(dest::Sym, x::Sym, pairs::Pair...; kwargs...)
    y = Sym(substitute(x, pairs...; kwargs...))
    sethead!(dest, gethead(y))
    setargs!(dest, getargs(y))
    return dest
end

"""
    substitute(x, pairs...; strict=false)

Using pairs of `pat => sub`, substitute occurences of `pat` in `x`
with `sub`.  If `strict` is `true`, only allow substitutions for which
the tag of `pat` is a subtype of the tag of `sub`.

"""
function substitute(x, pairs::Pair...; kwargs...)
    x = unprotect(_substitute(x, pairs...; kwargs...))
    return x
end

function _substitute(x, pairs::Pair...; kwargs...)
    pairs = map(pair -> Pair(convert(Sym, first(pair)), convert(Sym, last(pair))), pairs)
    return _substitute(x, pairs...; kwargs...)
end

# Catch all
_substitute(x, pairs::(Pair{<:Sym,<:Sym})...; kwargs...) = x

function _substitute(x::Sym, pairs::Pair{<:Sym,<:Sym}...; strict=false, context::Context = @__context__)
    for (pat, sub) in pairs
        if strict && !issubtag(tagof(sub), tagof(pat))
            error("strict mode: cannot substitute: $pat => $sub: $(tagof(sub)) is not a subtype of $(tagof(pat))")
        elseif isequal(x, pat)
            return sub
        end
    end
    isatomic(x) && return x
    args = map(arg -> _substitute(arg, pairs...; strict=strict, context=context), getargs(x))
    if hashead(x, :call)
        return apply(args...; context=context)
    else
        return combine(gethead(x), args...; context=context)
    end
end


text:
#TODO: Real tests =(
using go
using Base.Test

@test 1 == 1

# Very simple end-to-end sanity test
# Fits a linear model to examples from a single SGF file.
# Not going to be accurate, but tests simple
examples = go.generate_training_data("./example.sgf")
X = go.batch_training_examples([x[1] for x in examples])
Y = go.batch_training_examples([x[2][:] for x in examples])
clf = go.CLF_LINEAR(go.LIBERTIES)
go.train_model(clf, X, Y, epochs=100, validation_split=0.5)
b = go.Board()
move = go.choose_move(b, clf)


text:
using SafeTestsets

@safetestset "Linear Solvers                                                                  " begin include("linear_solvers_tests.jl") end
@safetestset "Jacobians                                                                       " begin include("jacobian_tests.jl") end
@safetestset "Nonlinear Solvers                                                               " begin include("nonlinear_solvers_tests.jl") end


text:
using AstroImageView
using AstroImageView: get_label, get_button, format_header, header_window, format_label, label_window
using AstroImages, GtkReactive, Gtk.ShortNames, Graphics, Gtk, Colors, IntervalSets, Cairo
using AstroImages: render
using WCS, FITSIO
using Test

@testset "labels" begin
    label = get_label("test")
    @test label isa GtkLabelLeaf
    @test get_gtk_property(label, :label, String) == "test"
end

@testset "butttons" begin
    btn = get_button("test")
    @test btn isa GtkToolButtonLeaf
    @test get_gtk_property(btn, :label, String) == "test"
    @test get_gtk_property(btn, :is_important, Bool) == true
end

@testset "format header" begin
    str = "testing the behaviour at line length 80 testing the behaviour at line length 80 testing the behaviour at line length 80 testing the behaviour at line length 80 testing the behaviour at line length 80 testing the behaviour at line length 80 "
    answer = "testing the behaviour at line length 80 testing the behaviour at line length 80 \ntesting the behaviour at line length 80 testing the behaviour at line length 80 \ntesting the behaviour at line length 80 testing the behaviour at line length 80 \n"
    @test answer == format_header(str)
end

@testset "header window" begin
    win = header_window(WCSTransform(2;))
    @test win isa GtkWindowLeaf
    @test win.txt isa Gtk.GLib.FieldRef{GtkWindowLeaf}
    @test get_gtk_property(win, :title, String) == "Header"
    @test get_gtk_property(win, :default_height, Int) == 500
    @test get_gtk_property(win, :default_width, Int) == 600
    destroy(win)
end

@testset "labels" begin
    img_labels = [((12.0,32.2), "This is a test label 1"), ((12.3,12.5), "This is a test label 2")]
    @test format_label(img_labels[1]) == ". (12.0,32.2)\tThis is a test label 1"

    win = label_window(img_labels)
    @test win isa GtkWindowLeaf
    @test win.txt isa Gtk.GLib.FieldRef{GtkWindowLeaf}
    @test get_gtk_property(win, :title, String) == "Labels"
    @test get_gtk_property(win, :default_height, Int) == 500
    @test get_gtk_property(win, :default_width, Int) == 600
    destroy(win)
end

@testset "basic panel" begin
    fname = tempname() * ".fits"
    inhdr = FITSHeader(["CTYPE1", "CTYPE2", "RADESYS", "FLTKEY", "INTKEY", "BOOLKEY", "STRKEY", "COMMENT",
                        "HISTORY"],
                       ["RA---TAN", "DEC--TAN", "UNK", 1.0, 1, true, "string value", nothing, nothing],
                       ["",
                        "",
                        "",
                        "floating point keyword",
                        "",
                        "boolean keyword",
                        "string value",
                        "this is a comment",
                        "this is a history"])

    indata = reshape(Float32[1:100;], 5, 20)
    FITS(fname, "w") do f
        write(f, indata; header=inhdr)
        write(f, indata; header=inhdr)
    end
    img = AstroImage(fname, (1,2))

    basic_ui = ui_basic(img)
    @test basic_ui isa GtkWindowLeaf
    @test get_gtk_property(basic_ui, :title, String) == "Image"
    @test basic_ui.g isa Gtk.GLib.FieldRef{GtkWindowLeaf}
    @test get_gtk_property(basic_ui, :default_height, Int) == 700
    @test get_gtk_property(basic_ui, :default_width, Int) == 700

    rm(fname, force = true)
    destroy(basic_ui)
end

@testset "advanced panel" begin
    fname = tempname() * ".fits"
    inhdr = FITSHeader(["CTYPE1", "CTYPE2", "RADESYS", "FLTKEY", "INTKEY", "BOOLKEY", "STRKEY", "COMMENT",
                        "HISTORY"],
                       ["RA---TAN", "DEC--TAN", "UNK", 1.0, 1, true, "string value", nothing, nothing],
                       ["",
                        "",
                        "",
                        "floating point keyword",
                        "",
                        "boolean keyword",
                        "string value",
                        "this is a comment",
                        "this is a history"])

    indata = reshape(Float32[1:100;], 5, 20)
    FITS(fname, "w") do f
        write(f, indata; header=inhdr)
        write(f, indata; header=inhdr)
    end
    img = AstroImage(fname, (1,2))

    adv_ui = ui_advanced(img)
    @test adv_ui isa GtkWindowLeaf
    @test get_gtk_property(adv_ui, :title, String) == "Image"
    @test adv_ui.g isa Gtk.GLib.FieldRef{GtkWindowLeaf}
    @test get_gtk_property(adv_ui, :default_height, Int) == 700
    @test get_gtk_property(adv_ui, :default_width, Int) == 700

    rm(fname, force = true)
    destroy(adv_ui)
end


text:
include("../common.jl")

build_harfbuzz(ARGS, "HarfBuzz")

max_stars_repo_name: jameskermode/Yggdrasil

max_issues_repo_name: jameskermode/Yggdrasil

max_forks_repo_name: jameskermode/Yggdrasil


text:
function readKey(stream::IO=terminal.in_stream)
    readNextChar() = Char(read(stream,1)[1])
    c = readNextChar()
    if c == '\x1b' # Escape
        esc_s = ""
        while isempty(esc_s) || esc_s[end] ∉ ['A','B','C','D','F','H','P','Q','R','S','~']
            esc_s *= readNextChar()
        end
        return esc_codes[esc_s]
    elseif Int(c) in 0:31
        return ctrl_codes[Int(c)]
    else
        return string(c)
    end
end

function testread()
    clear_screen()
    result = ""
    while result != "Ctrl-C"
        result = readKey()
        cursor_move_abs([0,0])
        cursor_deleteline()
        print("read: ", result)
    end
end

const esc_codes = Dict([
    "[A" => "Up",
    "[B" => "Down",
    "[C" => "Right",
    "[D" => "Left",
    "[F" => "End",
    "[H" => "Pos1",
    "[2~" => "Ins",
    "[3~" => "Del",
    "[5~" => "PgUp",
    "[6~" => "PdDown",
    "OP" => "F1",
    "OQ" => "F2",
    "OR" => "F3",
    "OS" => "F4",
    "[15~" => "F5",
    "[17~" => "F6",
    "[18~" => "F7",
    "[19~" => "F8",
    "[20~" => "F9",
    "[21~" => "F10",
    "[23~" => "F11",
    "[24~" => "F12",
    "[29~" => "Apps",
    "[34~" => "Win",
    "[1;2A" => "Shift-Up",
    "[1;2B" => "Shift-Down",
    "[1;2C" => "Shift-Right",
    "[1;2D" => "Shift-Left",
    "[1;2F" => "Shift-End",
    "[1;2H" => "Shift-Pos1",
    "[2;2~" => "Shift-Ins",
    "[3;2~" => "Shift-Del",
    "[5;2~" => "Shift-PgUp",
    "[6;2~" => "Shift-PdDown",
    "[1;2P" => "Shift-F1",
    "[1;2Q" => "Shift-F2",
    "[1;2R" => "Shift-F3",
    "[1;2S" => "Shift-F4",
    "[15;2~" => "Shift-F5",
    "[17;2~" => "Shift-F6",
    "[18;2~" => "Shift-F7",
    "[19;2~" => "Shift-F8",
    "[20;2~" => "Shift-F9",
    "[21;2~" => "Shift-F10",
    "[23;2~" => "Shift-F11",
    "[24;2~" => "Shift-F12",
    "[29;2~" => "Shift-Apps",
    "[34;2~" => "Shift-Win",
    "[1;3A" => "Meta-Up",
    "[1;3B" => "Meta-Down",
    "[1;3C" => "Meta-Right",
    "[1;3D" => "Meta-Left",
    "[1;3F" => "Meta-End",
    "[1;3H" => "Meta-Pos1",
    "[2;3~" => "Meta-Ins",
    "[3;3~" => "Meta-Del",
    "[5;3~" => "Meta-PgUp",
    "[6;3~" => "Meta-PdDown",
    "[1;3P" => "Meta-F1",
    "[1;3Q" => "Meta-F2",
    "[1;3R" => "Meta-F3",
    "[1;3S" => "Meta-F4",
    "[15;3~" => "Meta-F5",
    "[17;3~" => "Meta-F6",
    "[18;3~" => "Meta-F7",
    "[19;3~" => "Meta-F8",
    "[20;3~" => "Meta-F9",
    "[21;3~" => "Meta-F10",
    "[23;3~" => "Meta-F11",
    "[24;3~" => "Meta-F12",
    "[29;3~" => "Meta-Apps",
    "[34;3~" => "Meta-Win",
    "[1;5A" => "Ctrl-Up",
    "[1;5B" => "Ctrl-Down",
    "[1;5C" => "Ctrl-Right",
    "[1;5D" => "Ctrl-Left",
    "[1;5F" => "Ctrl-End",
    "[1;5H" => "Ctrl-Pos1",
    "[2;5~" => "Ctrl-Ins",
    "[3;5~" => "Ctrl-Del",
    "[5;5~" => "Ctrl-PgUp",
    "[6;5~" => "Ctrl-PdDown",
    "[1;5P" => "Ctrl-F1",
    "[1;5Q" => "Ctrl-F2",
    "[1;5R" => "Ctrl-F3",
    "[1;5S" => "Ctrl-F4",
    "[15;5~" => "Ctrl-F5",
    "[17;5~" => "Ctrl-F6",
    "[18;5~" => "Ctrl-F7",
    "[19;5~" => "Ctrl-F8",
    "[20;5~" => "Ctrl-F9",
    "[21;5~" => "Ctrl-F10",
    "[23;5~" => "Ctrl-F11",
    "[24;5~" => "Ctrl-F12",
    "[29;5~" => "Ctrl-Apps",
    "[34;5~" => "Ctrl-Win",
    "[1;6A" => "Shift-Ctrl-Up",
    "[1;6B" => "Shift-Ctrl-Down",
    "[1;6C" => "Shift-Ctrl-Right",
    "[1;6D" => "Shift-Ctrl-Left",
    "[1;6F" => "Shift-Ctrl-End",
    "[1;6H" => "Shift-Ctrl-Pos1",
    "[2;6~" => "Shift-Ctrl-Ins",
    "[3;6~" => "Shift-Ctrl-Del",
    "[5;6~" => "Shift-Ctrl-PgUp",
    "[6;6~" => "Shift-Ctrl-PdDown",
    "[1;6P" => "Shift-Ctrl-F1",
    "[1;6Q" => "Shift-Ctrl-F2",
    "[1;6R" => "Shift-Ctrl-F3",
    "[1;6S" => "Shift-Ctrl-F4",
    "[15;6~" => "Shift-Ctrl-F5",
    "[17;6~" => "Shift-Ctrl-F6",
    "[18;6~" => "Shift-Ctrl-F7",
    "[19;6~" => "Shift-Ctrl-F8",
    "[20;6~" => "Shift-Ctrl-F9",
    "[21;6~" => "Shift-Ctrl-F10",
    "[23;6~" => "Shift-Ctrl-F11",
    "[24;6~" => "Shift-Ctrl-F12",
    "[29;6~" => "Shift-Ctrl-Apps",
    "[34;6~" => "Shift-Ctrl-Win",
    "[1;7A" => "Ctrl-Meta-Up",
    "[1;7B" => "Ctrl-Meta-Down",
    "[1;7C" => "Ctrl-Meta-Right",
    "[1;7D" => "Ctrl-Meta-Left",
    "[1;7F" => "Ctrl-Meta-End",
    "[1;7H" => "Ctrl-Meta-Pos1",
    "[2;7~" => "Ctrl-Meta-Ins",
    "[3;7~" => "Ctrl-Meta-Del",
    "[5;7~" => "Ctrl-Meta-PgUp",
    "[6;7~" => "Ctrl-Meta-PdDown",
    "[1;7P" => "Ctrl-Meta-F1",
    "[1;7Q" => "Ctrl-Meta-F2",
    "[1;7R" => "Ctrl-Meta-F3",
    "[1;7S" => "Ctrl-Meta-F4",
    "[15;7~" => "Ctrl-Meta-F5",
    "[17;7~" => "Ctrl-Meta-F6",
    "[18;7~" => "Ctrl-Meta-F7",
    "[19;7~" => "Ctrl-Meta-F8",
    "[20;7~" => "Ctrl-Meta-F9",
    "[21;7~" => "Ctrl-Meta-F10",
    "[23;7~" => "Ctrl-Meta-F11",
    "[24;7~" => "Ctrl-Meta-F12",
    "[29;7~" => "Ctrl-Meta-Apps",
    "[34;7~" => "Ctrl-Meta-Win"
])

const ctrl_codes = Dict([
    0 => "Ctrl-2",
    1 => "Ctrl-A",
    2 => "Ctrl-B",
    3 => "Ctrl-C",
    4 => "Ctrl-D",
    5 => "Ctrl-E",
    6 => "Ctrl-F",
    7 => "Ctrl-G",
    8 => "Backspace",
    9 => "Tab",
    10 => "Ctrl-J",
    11 => "Ctrl-K",
    12 => "Ctrl-L",
    13 => "Enter",
    14 => "Ctrl-N",
    15 => "Ctrl-O",
    16 => "Ctrl-P",
    17 => "Ctrl-Q",
    18 => "Ctrl-R",
    19 => "Ctrl-S",
    20 => "Ctrl-T",
    21 => "Ctrl-U",
    22 => "Ctrl-V",
    23 => "Ctrl-W",
    24 => "Ctrl-X",
    25 => "Ctrl-Y",
    26 => "Ctrl-Z",
    27 => "Ctrl-3",
    29 => "Ctrl-5",
    30 => "Ctrl-6",
    31 => "Ctrl-7"
])


text:
module DesignByContract
using MacroTools
include("./agreements.jl")
include("./functionContract.jl")
include("./loopContract.jl")

export @contract, @loopinvariant, setAgreementEnabling, ContractBreachException

end # module


text:
module Simulators

# FIXME: automate this:
module rnn
include("rnn/_helper.jl")
module loop
include("rnn/loop.jl")
end
module vec
include("rnn/vec.jl")
end
end

module gcm
include("gcm/_helper.jl")
module loop
include("gcm/loop.jl")
end
module vec
include("gcm/vec.jl")
end
end

module oup
include("oup/_helper.jl")
module loop
include("oup/loop.jl")
end
end

this_module = current_module()

function getnestedfield(value, path::AbstractString)
    getnestedfield(value, map(Symbol, split(path, "."))...)
end

function getnestedfield(value, name::Symbol, rest::Symbol...)
    getnestedfield(getfield(value, name), rest...)
end
getnestedfield(value) = value

function prepare(module_name, run_name)
    getnestedfield(this_module, module_name).prepare(Symbol(run_name))
end

end

max_stars_repo_name: tkf/comparatist

max_issues_repo_name: tkf/comparatist

max_forks_repo_name: tkf/comparatist


text:
"""
    function bisection_loop!(args...; kwargs)

Takes a a bid range [bid_lo, bid_hi] and returns the bid which maximises the profit of the
Generator at the slack bus using the Transmission Constrained Residual Demand Derivative
(TCRDD). This is the second part of the full algorithm.

Detailed description: The algorithm is composed by two parts, (1) the Local Screening Loop
(LSL) and (2) the Bisection Loop (BL). The screening loop uses the initial bid0 and creates
an aproximation of the profit function. Using this aproximation, it identifies the range
[bid lower (bid_lo) and bid higher (bid_hi)] in which the bid that maximises the generator
profit could be. Once the lower and upper bid range are identified, the bisection loop will
find try to find if the approximations of the lower and upper bid intersect at some point.
If they do, the intersection bid is used to find a closer upper and lower range, or identi-
fy if the optimum has been found. If they dont intersect then, traditional bisection is done
until the bid that maximises the generators profit is found [1].

[1] L. Xu, R. Baldick and Y. Sutjandra, "Bidding Into Electricity Markets:
    A Transmission-Constrained Residual Demand Derivative Approach," in IEEE
    Transactions on Power Systems, vol. 26, no. 3, pp. 1380-1388, Aug. 2011,
    doi: 10.1109/TPWRS.2010.2083702.

# Arguments
- `sys::System`:                            Power system in p.u. (from PowerSystems.jl)
- `bid_lo::Float64`:                        Lower Bid for the slack generator [pu]
- `bid_hi::Float64`:                        Higher Bid for the slack generator [pu]
- `Pmin_orig::Float64`:                     Active power minimum limit Slack gen [pu]
- `Pmax_orig::Float64`:                     Active power maximum limit Slack gen [pu]
- `stop::Bool`:                             Flag to stop the algorithm

# Keywords
- `maxit_bi::Int64 = 30`:                   Maximum number of iterations for Bisection Loop
- `network::DataType = StandardPTDFModel`:  Network Representation of the Power System
- `solver= optimizer_with_attributes
    (Ipopt.Optimizer)`:                     Solver to be used for OPF
- `print_plots::Bool = true`:               Flag to print plots
- `segm_bid_argmax_profit::Int64 = 50000:   Segments to evaluate the approx profit function
- `epsilon::Float64 = 0.01`:                Convergence tolerance  bid_lo - bid_hi < epsilon
- `print_progress::Bool = true`:            Flag to print progress
- `dual_lines_tol::Float64 = 1e-1`:         Tolerance to identify any binding lines
- `dual_gen_tol::Float64 = 1e-1`:           Tolerance to identify any binding generators

"""
function bisection_loop!(
    sys::System,
    BaseMVA::Float64,
    bid_lo::Float64,
    bid_hi::Float64,
    Pmin_orig::Float64,
    Pmax_orig::Float64,
    stop::Bool;
    maxit_bi::Int64,
    network::DataType = StandardPTDFModel,
    solver = optimizer_with_attributes(Ipopt.Optimizer),
    print_plots::Bool = true,
    segm_bid_argmax_profit::Int64 = 50000,
    epsilon::Float64 = 0.01,
    print_progress::Bool = true,
    dual_lines_tol::Float64 = 1e-1,
    dual_gen_tol::Float64 = 1e-1
    )

    # Bisection Loop
    println("Bisection Loop")

    # Initial conditions
    iter_bi = 0
    same_tan_inv_lo_hi = false
    intersect_tan_inv_lo_hi = false
    bid_opt_found = false
    bid_mid = 0.5*(bid_lo + bid_hi)
    bid_intersect = bid_mid
    bid_opt = bid_mid

    # Get Slack Generator
    gen_thermal_slack, gen_thermal_slack_id, gen_thermal_slack_name = get_thermal_slack(sys)

    #  Algorithm Loops
    while (iter_bi <= maxit_bi && stop == false)
        iter_bi = iter_bi + 1
        # step 1 BL
        if abs(bid_hi - bid_lo) < epsilon
            bid_opt_found = true
            bid_opt = 0.5*(bid_lo + bid_hi)
            println("Local optimum found in", bid_opt)
            stop = true
            break
        # step 2 BL
        else
            # Calculate bisection point bid_mid
            # Calculations when bid = bid_lo
            # Change active power Limits to Bidmin = Pmin_orig Bidmax = bid_lo
            set_active_power_limits!(gen_thermal_slack, (min = Pmin_orig, max = bid_lo))
            # Solve PTDF OPF
            lmp_lo, res_lo = opf_PTDF(sys; network, solver)
            # Calculate TCRDD
            tcrdd_slack_lo = f_TCRDD(sys, res_lo; dual_lines_tol, dual_gen_tol)
            # Evaluate Profit
            profit_argmax_lo, bid_argmax_lo = bid_argmax_profit(
                sys,
                res_lo,
                BaseMVA,
                lmp_lo,
                tcrdd_slack_lo,
                bid_lo,
                Pmin_orig,
                Pmax_orig;
                segm_bid_argmax_profit,
                print_plots
            )

            # Calculations when bid = bid_hi
            # Change active power Limits to Bidmin = Pmin_orig Bidmax = bid_hi
            set_active_power_limits!(gen_thermal_slack, (min = Pmin_orig, max = bid_hi))
            # Solve PTDF OPF
            (lmp_hi, res_hi) = opf_PTDF(sys; network, solver)
            # Calculate TCRDD
            tcrdd_slack_hi = f_TCRDD(sys, res_hi; dual_lines_tol, dual_gen_tol)
            # Evaluate Profit
            profit_argmax_hi, bid_argmax_hi = bid_argmax_profit(
                sys,
                res_hi,
                BaseMVA,
                lmp_hi,
                tcrdd_slack_hi,
                bid_hi,
                Pmin_orig,
                Pmax_orig;
                segm_bid_argmax_profit,
                print_plots
            )

            # Check if the inverse tangent of the RDC is the same for both functions
            comparison_res = compare_tan_inv_RDC(
                sys,
                BaseMVA,
                res_lo,
                res_hi,
                lmp_lo,
                lmp_hi,
                tcrdd_slack_lo,
                tcrdd_slack_hi,
                bid_lo,
                bid_hi,
                Pmin_orig,
                Pmax_orig;
                segm_bid_argmax_profit,
                epsilon,
                print_plots
            )
            # Unpack the results of the comparison
            same_tan_inv_lo_hi, intersect_tan_inv_lo_hi, bid_intersect = comparison_res

            # Find bid_mid depending on the the case
            if same_tan_inv_lo_hi
                #tan_inv_RDC is the same for both hi and lo
                bid_mid = bid_argmax_lo
            elseif !intersect_tan_inv_lo_hi ||
                    ( intersect_tan_inv_lo_hi &&
                        (bid_intersect < bid_lo || bid_hi < bid_intersect) )
                # They dont intersect or intersect out of range, do traditional bisection
                bid_mid = 0.5*(bid_hi + bid_lo)
            else
                # Functions are different but they intersect within range
                # Determine profit maximiser range (Table 1 of reference [1])
                # Check where is the hump
                belong_bid_lo_intsct = false
                belong_bid_hi_intsct = false
                if (bid_lo <= bid_argmax_lo && bid_argmax_lo <= bid_intersect)
                    belong_bid_lo_intsct = true
                end
                if (bid_intersect <= bid_argmax_hi && bid_argmax_hi <= bid_hi)
                    belong_bid_hi_intsct = true
                end
                # Select bid_mid
                if !belong_bid_lo_intsct && !belong_bid_hi_intsct #no hump
                    bid_mid = bid_intersect
                elseif belong_bid_lo_intsct && !belong_bid_hi_intsct #left hump
                    bid_mid = bid_argmax_lo
                elseif !belong_bid_lo_intsct && belong_bid_hi_intsct #right hump
                    bid_mid = bid_argmax_hi
                elseif belong_bid_lo_intsct && belong_bid_hi_intsct #double hump
                    # Select the side based on profit_argmax
                    if profit_argmax_hi >= profit_argmax_lo
                        bid_mid = bid_argmax_hi
                    else
                        bid_mid = bid_argmax_lo
                    end
                end
            end
        end
        # Step 3 BL
        # Calculations when bid = bid_mid
        # Change active power Limits to Bidmin = Pmin_orig Bidmax = bid_mid
        set_active_power_limits!(gen_thermal_slack, (min = Pmin_orig, max = bid_mid))
        # Solve PTDF OPF
        lmp_mid, res_mid = opf_PTDF(sys; network, solver)
        # Calculate TCRDD
        tcrdd_slack_mid = f_TCRDD(sys, res_mid; dual_lines_tol, dual_gen_tol)
        # Evaluate Profit
        profit_argmax_mid, bid_argmax_mid = bid_argmax_profit(
            sys,
            res_mid,
            BaseMVA,
            lmp_mid,
            tcrdd_slack_mid,
            bid_mid,
            Pmin_orig,
            Pmax_orig;
            segm_bid_argmax_profit,
            print_plots
        )

        if intersect_tan_inv_lo_hi
            # Calculations when bid = bid_intersect
            # Change active power Limits to Bidmin = Pmin_orig Bidmax = bid_intersect
            set_active_power_limits!(
                gen_thermal_slack,
                (min = Pmin_orig, max = bid_intersect)
            )
            # Solve PTDF OPF
            lmp_intersect, res_intersect = opf_PTDF(sys; network, solver)
        end

        # Step 4 BL
        if bid_argmax_mid == bid_mid
            bid_opt_found = true
            bid_opt = bid_mid
            println("Local optimum found in", bid_opt)
            stop = true
            break
        # Step 5 BL
        elseif intersect_tan_inv_lo_hi && (bid_mid == bid_intersect) &&
            (lmp_mid == lmp_intersect)
            # Do an Incremental test
            if tcrdd_slack_mid == tcrdd_slack_lo
                bid_int_epsil = bid_intersect + epsilon
                # Calculations when bid = bid_int_epsil
                # Change active power Limits to Bidmin = Pmin_orig Bidmax = bid_int_epsil
                set_active_power_limits!(
                    gen_thermal_slack,
                    (min = Pmin_orig, max = bid_int_epsil)
                )
                # Solve PTDF OPF
                lmp_int_epsil, res_int_epsil = opf_PTDF(sys; network, solver)
                # Calculate TCRDD
                tcrdd_slack_int_epsil = f_TCRDD(
                    sys,
                    res_int_epsil;
                    dual_lines_tol,
                    dual_gen_tol
                )
                # Evaluate Profit
                profit_argmax_int_epsil, bid_argmax_int_epsil = bid_argmax_profit(
                    sys,
                    res_int_epsil,
                    BaseMVA,
                    lmp_int_epsil,
                    tcrdd_slack_int_epsil,
                    bid_int_epsil,
                    Pmin_orig,
                    Pmax_orig;
                    segm_bid_argmax_profit,
                    print_plots
                )
                if bid_argmax_int_epsil <= bid_int_epsil
                    bid_opt_found = true
                    bid_opt = bid_intersect
                    println("Local optimum found in", bid_opt)
                    stop = true
                    break
                end
            elseif tcrdd_slack_mid == tcrdd_slack_hi
                bid_int_epsil = bid_intersect - epsilon
                # Calculations when bid = bid_int_epsil
                # Change active power Limits to Bidmin = Pmin_orig Bidmax = bid_int_epsil
                set_active_power_limits!(
                    gen_thermal_slack,
                    (min = Pmin_orig, max = bid_int_epsil)
                )
                # Solve PTDF OPF
                lmp_int_epsil, res_int_epsil = opf_PTDF(sys; network, solver)
                # Calculate TCRDD
                tcrdd_slack_int_epsil = f_TCRDD(
                    sys,
                    res_int_epsil;
                    dual_lines_tol,
                    dual_gen_tol
                )
                # Evaluate Profit
                profit_argmax_int_epsil, bid_argmax_int_epsil = bid_argmax_profit(
                    sys,
                    res_int_epsil,
                    BaseMVA,
                    lmp_int_epsil,
                    tcrdd_slack_int_epsil,
                    bid_int_epsil,
                    Pmin_orig,
                    Pmax_orig;
                    segm_bid_argmax_profit,
                    print_plots
                )
                if bid_argmax_int_epsil >= bid_int_epsil
                    bid_opt_found = true
                    bid_opt = bid_intersect
                    println("Local optimum found in", bid_opt)
                    stop = true
                    break
                end
            end
        end
        # Step 6 BL
        #Traditional Bisection
        if bid_mid < bid_argmax_mid
            bid_lo = bid_mid
            # bid_hi remains the same
        else # bid_argmax_mid < bid_mid
            bid_hi = bid_mid
            # bid_lo remains the same
        end

        if print_progress
            a=println("Bisection Loop iter: ", iter_bi)
            b=println("Optimal bid found: ", bid_opt_found)
            c=println("Stop Flag: ", stop)
            d=println("Bidmid: ", bid_mid)
            e=println("Optimal Bid Value: ", bid_opt)
            f=println("Local optimum exists in: [ ",bid_lo," , ",bid_hi," ]")
            g=println("LMP aprox Intersect Flag: ", intersect_tan_inv_lo_hi)
            h=println("Bid Intersect: ", bid_intersect)
        end
    end

    return stop, iter_bi, bid_opt_found, bid_opt, bid_mid
end

max_stars_repo_name: invenia/MaximumGeneratorProfitTCRDD

max_issues_repo_name: invenia/MaximumGeneratorProfitTCRDD

max_forks_repo_name: invenia/MaximumGeneratorProfitTCRDD


text:
# ------------------------------------------------------------------
# Licensed under the MIT License. See LICENSE in the project root.
# ------------------------------------------------------------------

"""
    GeoWeights(domain, weights)

Assign `weights` to each point in spatial `domain`.

### Notes

Implement AbstractWeights interface from StatsBase.jl.
"""
mutable struct GeoWeights{S,T,V<:AbstractVector{T},D} <: AbstractWeights{S,T,V}
  domain::D
  values::V
  sum::S
end

GeoWeights(domain::D, values::V) where {D,V} =
  GeoWeights(domain, values, sum(values))

Meshes.domain(w::GeoWeights) = w.domain

@inline function varcorrection(w::GeoWeights, corrected::Bool=false)
    corrected && throw(ArgumentError("GeoWeights type does not support bias correction."))
    1 / w.sum
end

# ------------
# IO methods
# ------------
function Base.show(io::IO, w::GeoWeights)
  npts = nelements(w.domain)
  print(io, "$npts GeoWeights")
end

function Base.show(io::IO, ::MIME"text/plain", w::GeoWeights)
  println(io, w)
  Base.print_array(io, w.values)
end

"""
    WeightingMethod

A method to weight spatial data.
"""
abstract type WeightingMethod end

"""
    weight(object, method)

Weight spatial `object` with `method`.
"""
function weight end

# ----------------
# IMPLEMENTATIONS
# ----------------
include("weighting/uniform.jl")
include("weighting/block.jl")
include("weighting/densratio.jl")


text:
# This file is a part of BAT.jl, licensed under the MIT License (MIT).

using BAT
using Test

using Distributions, StatsBase, ValueShapes
using ForwardDiff

@testset "forwarddiff" begin
    posterior = ForwardDiffAD()|BAT.example_posterior()

    mh_notrafo_sampling_alg = MCMCSampling(
        mcalg = MetropolisHastings(),
        nchains = 2,
        nsteps = 10^4,
        trafo = NoDensityTransform(),
        burnin = MCMCMultiCycleBurnin(nsteps_per_cycle = 1000, max_ncycles = 2),
        strict = false
    )

    hmc_sampling_alg = MCMCSampling(
        mcalg = HamiltonianMC(),
        nchains = 2,
        nsteps = 100,
        init = MCMCChainPoolInit(init_tries_per_chain = 2, nsteps_init = 5),
        burnin = MCMCMultiCycleBurnin(nsteps_per_cycle = 100, max_ncycles = 1),
        strict = false
    )

    # Test basic sampling of posterior wrapped in DensityWithDiff works, with all required functions forwarded:
    @test @inferred(bat_sample(posterior, mh_notrafo_sampling_alg)).result isa DensitySampleVector

    v = rand(posterior.density.prior)
    f = logdensityof(posterior)
    gradlogp = valgradof(f)
    @test @inferred(gradlogp(v))[1] == f(v)
    @test @inferred(gradlogp(v))[2] == gradient_shape(varshape(posterior))(ForwardDiff.gradient(unshaped(f), (unshaped(v, varshape(posterior)))))

    @test bat_sample(posterior, hmc_sampling_alg).result isa DensitySampleVector
end


text:
module TestFundamentals
using AlphaVantage
using Test

TEST_SLEEP_TIME =  parse(Float64, get(ENV, "TEST_SLEEP_TIME", "15"))
MAX_TESTS = parse(Int64, get(ENV, "MAX_TESTS", "1"))

@testset "Fundamentals" begin
    symbol = "IBM"

    @testset "Overview" begin
        data = company_overview(symbol)
        @test typeof(data) === Dict{String, Any}
        @test length(data) === 59
        sleep(TEST_SLEEP_TIME + 2*rand()) #as to not overload the API
    end

    @testset "Income Statement" begin
        data = income_statement(symbol)
        @test typeof(data) === Dict{String, Any}
        @test length(data) === 3
        sleep(TEST_SLEEP_TIME + 2*rand()) #as to not overload the API
    end

    @testset "Balance Sheet" begin
        data = balance_sheet(symbol)
        @test typeof(data) === Dict{String, Any}
        @test length(data) === 3
        sleep(TEST_SLEEP_TIME + 2*rand()) #as to not overload the API
    end

    @testset "Cash Flow" begin
        data = cash_flow(symbol)
        @test typeof(data) === Dict{String, Any}
        @test length(data) === 3
        sleep(TEST_SLEEP_TIME + 2*rand()) #as to not overload the API
    end

    @testset "Earnings" begin
        data = earnings(symbol)
        @test typeof(data) === Dict{String, Any}
        @test length(data) === 3
        sleep(TEST_SLEEP_TIME + 2*rand()) #as to not overload the API
    end

    @testset "Listing Status" begin
        @testset "Default" begin
            data = listing_status()
            @test length(data) == 2
        end

        @testset "Delisted and Date" begin
            data = listing_status(state = "delisted", date = "2020-12-17")
            @test length(data) == 2
        end
    end

end

end # module