"""
			
			    Upsample(mode = :nearest; [scale, size]) 
			    Upsample(scale, mode = :nearest)  
			
			An upsampling layer. One of two keywords must be given:
			
			If `scale` is a number, this applies to all but the last two dimensions (channel and batch) of the input. 
			It may also be a tuple, to control dimensions individually. Alternatively, keyword 
			`size` accepts a tuple, to directly specify the leading dimensions of the output.
			
			Currently supported upsampling `mode`s 
			and corresponding NNlib's methods are:
			  - `:nearest` -> [`NNlib.upsample_nearest`](@ref) 
			  - `:bilinear` -> [`NNlib.upsample_bilinear`](@ref)
			  - `:trilinear` -> [`NNlib.upsample_trilinear`](@ref)
			
			# Examples
			
			```jldoctest
			julia> m = Upsample(scale = (2, 3))
			Upsample(:nearest, scale = (2, 3))
			
			julia> m(ones(2, 2, 1, 1)) |> size
			(4, 6, 1, 1)
			
			julia> m = Upsample(:bilinear, size = (4, 5))
			Upsample(:bilinear, size = (4, 5))
			
			julia> m(ones(2, 2, 1, 1)) |> size
			(4, 5, 1, 1)
			```
			"""
			
			
			
			struct
			 
			
	
			Upsample
			{
			mode
			,
			 
			S
			,
			 
			T
			}
			
			
  
			
			scale
			::
			S
			
  
			
			size
			::
			T
			
			end
			
			
			
			function
			 
			
	
			Upsample
			(
			
			
			mode
			::
			Symbol
			 
			=
			 
			
			:
			nearest
			
			;
			 
			
			scale
			 
			=
			 
			nothing
			,
			 
			
			size
			 
			=
			 
			nothing
			)
			
			
  
			
			
			mode
			 
			in
			 
			
			[
			
			:
			nearest
			,
			 
			
			:
			bilinear
			,
			 
			
			:
			trilinear
			]
			 
			||
			 
    
			
			throw
			(
			
			ArgumentError
			(
			
			"
			mode=:
			$
			mode
			 is not supported.
			"
			)
			)
			
  
			
			if
			 
			
			!
			(
			
			
			isnothing
			(
			scale
			)
			 
			⊻
			 
			
			isnothing
			(
			size
			)
			)
			
			
    
			
			throw
			(
			
			ArgumentError
			(
			
			"
			Either scale or size should be specified (but not both).
			"
			)
			)
			
  
			end
			
  
			
			return
			 
			
			
	
			Upsample
			{
			mode
			,
			
			typeof
			(
			scale
			)
			,
			
			typeof
			(
			size
			)
			}
			(
			scale
			,
			 
			size
			)
			
			end
			
			
			
			
	
			Upsample
			(
			scale
			,
			 
			
			
			mode
			::
			Symbol
			 
			=
			 
			
			:
			nearest
			)
			 
			=
			 
			
	
			Upsample
			(
			mode
			
			;
			 
			scale
			)
			
			
			
			
			(
			
			m
			::
			
	
			Upsample
			{
			
			:
			nearest
			}
			)
			(
			
			x
			::
			AbstractArray
			)
			 
			=
			
  
			
			
			NNlib
			.
			
			upsample_nearest
			(
			x
			,
			 
			
			m
			.
			
			scale
			)
			
			
			function
			 
			
			
			(
			
			m
			::
			
	
			Upsample
			{
			
			:
			nearest
			,
			 
			Int
			}
			)
			(
			
			x
			::
			
			AbstractArray
			{
			T
			,
			 
			N
			}
			)
			 
			where
			 
			{
			T
			,
			 
			N
			}
			
			 
  
			
			
			NNlib
			.
			
			upsample_nearest
			(
			x
			,
			 
			
			ntuple
			(
			
			i
			 
			->
			 
			
			m
			.
			
			scale
			,
			 
			
			N
			-
			2
			)
			)
			
			end
			
			
			
			(
			
			m
			::
			
	
			Upsample
			{
			
			:
			nearest
			,
			 
			Nothing
			}
			)
			(
			
			x
			::
			AbstractArray
			)
			 
			=
			
  
			
			
			NNlib
			.
			
			upsample_nearest
			(
			x
			
			;
			 
			
			size
			=
			
			m
			.
			
			size
			)
			
			
			
			
			(
			
			m
			::
			
	
			Upsample
			{
			
			:
			bilinear
			}
			)
			(
			
			x
			::
			AbstractArray
			)
			 
			=
			
  
			
			
			NNlib
			.
			
			upsample_bilinear
			(
			x
			,
			 
			
			m
			.
			
			scale
			)
			
			
			
			(
			
			m
			::
			
	
			Upsample
			{
			
			:
			bilinear
			,
			 
			Nothing
			}
			)
			(
			
			x
			::
			AbstractArray
			)
			 
			=
			 
  
			
			
			NNlib
			.
			
			upsample_bilinear
			(
			x
			
			;
			 
			
			size
			=
			
			m
			.
			
			size
			)
			
			
			
			
			(
			
			m
			::
			
	
			Upsample
			{
			
			:
			trilinear
			}
			)
			(
			
			x
			::
			AbstractArray
			)
			 
			=
			
  
			
			
			NNlib
			.
			
			upsample_trilinear
			(
			x
			,
			 
			
			m
			.
			
			scale
			)
			
			
			
			(
			
			m
			::
			
	
			Upsample
			{
			
			:
			trilinear
			,
			 
			Nothing
			}
			)
			(
			
			x
			::
			AbstractArray
			)
			 
			=
			 
  
			
			
			NNlib
			.
			
			upsample_trilinear
			(
			x
			
			;
			 
			
			size
			=
			
			m
			.
			
			size
			)
			
			
			
			function
			 
			
			
			
			Base
			.
			
			show
			(
			
			io
			::
			IO
			,
			 
			
			u
			::
			
	
			Upsample
			{
			mode
			}
			)
			 
			where
			 
			{
			mode
			}
			
			
  
			
			print
			(
			io
			,
			 
			
			"
			Upsample(
			"
			)
			
  
			
			print
			(
			io
			,
			 
			
			"
			:
			"
			,
			 
			mode
			)
			
  
			
			
			
			u
			.
			
			scale
			 
			!==
			 
			nothing
			 
			&&
			 
			
			print
			(
			io
			,
			 
			
			"
			, scale = 
			$
			(
			
			u
			.
			
			scale
			)
			"
			)
			
  
			
			
			
			u
			.
			
			size
			 
			!==
			 
			nothing
			 
			&&
			 
			
			print
			(
			io
			,
			 
			
			"
			, size = 
			$
			(
			
			u
			.
			
			size
			)
			"
			)
			
  
			
			print
			(
			io
			,
			 
			
			"
			)
			"
			)
			
			end
			
			
			
			
			
			"""
			
			    PixelShuffle(r::Int)
			
			Pixel shuffling layer with upscale factor `r`. Usually used for generating higher
			resolution images while upscaling them.
			 
			See [`NNlib.pixel_shuffle`](@ref).
			
			# Examples
			```jldoctest
			julia> p = PixelShuffle(2);
			
			julia> xs = [2row + col + channel/10 for row in 1:2, col in 1:2, channel in 1:4, n in 1:1]
			2×2×4×1 Array{Float64, 4}:
			[:, :, 1, 1] =
			 3.1  4.1
			 5.1  6.1
			
			[:, :, 2, 1] =
			 3.2  4.2
			 5.2  6.2
			
			[:, :, 3, 1] =
			 3.3  4.3
			 5.3  6.3
			
			[:, :, 4, 1] =
			 3.4  4.4
			 5.4  6.4
			
			julia> p(xs)
			4×4×1×1 Array{Float64, 4}:
			[:, :, 1, 1] =
			 3.1  3.3  4.1  4.3
			 3.2  3.4  4.2  4.4
			 5.1  5.3  6.1  6.3
			 5.2  5.4  6.2  6.4
			
			julia> xs = [3row + col + channel/10 for row in 1:2, col in 1:3, channel in 1:4, n in 1:1]
			2×3×4×1 Array{Float64, 4}:
			[:, :, 1, 1] =
			 4.1  5.1  6.1
			 7.1  8.1  9.1
			
			[:, :, 2, 1] =
			 4.2  5.2  6.2
			 7.2  8.2  9.2
			
			[:, :, 3, 1] =
			 4.3  5.3  6.3
			 7.3  8.3  9.3
			
			[:, :, 4, 1] =
			 4.4  5.4  6.4
			 7.4  8.4  9.4
			
			julia> p(xs)
			4×6×1×1 Array{Float64, 4}:
			[:, :, 1, 1] =
			 4.1  4.3  5.1  5.3  6.1  6.3
			 4.2  4.4  5.2  5.4  6.2  6.4
			 7.1  7.3  8.1  8.3  9.1  9.3
			 7.2  7.4  8.2  8.4  9.2  9.4
			```
			"""
			
			
			
			struct
			 
	
			PixelShuffle
			
			 
  
			
			r
			::
			Int
			
			end
			
			
			
			
			(
			
			m
			::
	
			PixelShuffle
			)
			(
			x
			)
			 
			=
			 
			
			
			NNlib
			.
			
			pixel_shuffle
			(
			x
			,
			 
			
			m
			.
			
			r
			)