text:
# define picoscope error type
export PicoStatus

bitstype 32 PicoStatus <: Unsigned
Base.convert(::Type{PicoStatus}, x::UInt32) = reinterpret(PicoStatus,x)
Base.convert(::Type{UInt32}, x::PicoStatus) = reinterpret(UInt32,x)
Base.promote_rule(::Type{PicoStatus}, ::Type{UInt32}) = UInt32
function Base.show(io::IO, x::PicoStatus)
  show(reinterpret(UInt32,x))
end

type PicoScopeError <: Exception
  picostatus :: PicoStatus
end

module PICO_STATUS
  const PICO_OK = 0x00000000
  const PICO_MAX_UNITS_OPENED = 0x00000001
  const PICO_MEMORY_FAIL = 0x00000002
  const PICO_NOT_FOUND = 0x00000003
  const PICO_FW_FAIL = 0x00000004
  const PICO_OPEN_OPERATION_IN_PROGRESS = 0x00000005
  const PICO_OPERATION_FAILED = 0x00000006
  const PICO_NOT_RESPONDING = 0x00000007
  const PICO_CONFIG_FAIL = 0x00000008
  const PICO_KERNEL_DRIVER_TOO_OLD = 0x00000009
  const PICO_EEPROM_CORRUPT = 0x0000000a
  const PICO_OS_NOT_SUPPORTED = 0x0000000b
  const PICO_INVALID_HANDLE = 0x0000000c
  const PICO_INVALID_PARAMETER = 0x0000000d
  const PICO_INVALID_TIMEBASE = 0x0000000e
  const PICO_INVALID_VOLTAGE_RANGE = 0x0000000f
  const PICO_INVALID_CHANNEL = 0x00000010
  const PICO_INVALID_TRIGGER_CHANNEL = 0x00000011
  const PICO_INVALID_CONDITION_CHANNEL = 0x00000012
  const PICO_NO_SIGNAL_GENERATOR = 0x00000013
  const PICO_STREAMING_FAILED = 0x00000014
  const PICO_BLOCK_MODE_FAILED = 0x00000015
  const PICO_NULL_PARAMETER = 0x00000016
  const PICO_ETS_MODE_SET = 0x00000017
  const PICO_DATA_NOT_AVAILABLE = 0x00000018
  const PICO_STRING_BUFFER_TOO_SMALL = 0x00000019
  const PICO_ETS_NOT_SUPPORTED = 0x0000001a
  const PICO_AUTO_TRIGGER_TIME_TOO_SHORT = 0x0000001b
  const PICO_BUFFER_STALL = 0x0000001c
  const PICO_TOO_MANY_SAMPLES = 0x0000001d
  const PICO_TOO_MANY_SEGMENTS = 0x0000001e
  const PICO_PULSE_WIDTH_QUALIFIER = 0x0000001f
  const PICO_DELAY = 0x00000020
  const PICO_SOURCE_DETAILS = 0x00000021
  const PICO_CONDITIONS = 0x00000022
  const PICO_USER_CALLBACK = 0x00000023
  const PICO_DEVICE_SAMPLING = 0x00000024
  const PICO_NO_SAMPLES_AVAILABLE = 0x00000025
  const PICO_SEGMENT_OUT_OF_RANGE = 0x00000026
  const PICO_BUSY = 0x00000027
  const PICO_STARTINDEX_INVALID = 0x00000028
  const PICO_INVALID_INFO = 0x00000029
  const PICO_INFO_UNAVAILABLE = 0x0000002a
  const PICO_INVALID_SAMPLE_INTERVAL = 0x0000002b
  const PICO_TRIGGER_ERROR = 0x0000002c
  const PICO_MEMORY = 0x0000002d
  const PICO_SIG_GEN_PARAM = 0x0000002e
  const PICO_SHOTS_SWEEPS_WARNING = 0x0000002f
  const PICO_SIGGEN_TRIGGER_SOURCE = 0x00000030
  const PICO_AUX_OUTPUT_CONFLICT = 0x00000031
  const PICO_AUX_OUTPUT_ETS_CONFLICT = 0x00000032
  const PICO_WARNING_EXT_THRESHOLD_CONFLICT = 0x00000033
  const PICO_WARNING_AUX_OUTPUT_CONFLICT = 0x00000034
  const PICO_SIGGEN_OUTPUT_OVER_VOLTAGE = 0x00000035
  const PICO_DELAY_NULL = 0x00000036
  const PICO_INVALID_BUFFER = 0x00000037
  const PICO_SIGGEN_OFFSET_VOLTAGE = 0x00000038
  const PICO_SIGGEN_PK_TO_PK = 0x00000039
  const PICO_CANCELLED = 0x0000003a
  const PICO_SEGMENT_NOT_USED = 0x0000003b
  const PICO_INVALID_CALL = 0x0000003c
  const PICO_GET_VALUES_INTERRUPTED = 0x0000003d
  const PICO_NOT_USED = 0x0000003f
  const PICO_INVALID_SAMPLERATIO = 0x00000040
  const PICO_INVALID_STATE = 0x00000041
  const PICO_NOT_ENOUGH_SEGMENTS = 0x00000042
  const PICO_DRIVER_FUNCTION = 0x00000043
  const PICO_RESERVED = 0x00000044
  const PICO_INVALID_COUPLING = 0x00000045
  const PICO_BUFFERS_NOT_SET = 0x00000046
  const PICO_RATIO_MODE_NOT_SUPPORTED = 0x00000047
  const PICO_RAPID_NOT_SUPPORT_AGGREGATION = 0x00000048
  const PICO_INVALID_TRIGGER_PROPERTY = 0x00000049
  # below here in header file only
  const PICO_RESISTANCE_AND_PROBE_NOT_ALLOWED     = 0x0000004B
  const PICO_POWER_FAILED                         = 0x0000004C
  const PICO_SIGGEN_WAVEFORM_SETUP_FAILED         = 0x0000004D
  const PICO_FPGA_FAIL                            = 0x0000004E
  const PICO_POWER_MANAGER                        = 0x0000004F
  const PICO_INVALID_ANALOGUE_OFFSET              = 0x00000050
  # unable to configure the ps2000a
  const PICO_PLL_LOCK_FAILED                      = 0x00000051
  # the ps2000a Analog board is not detectly connected
  # to the digital board
  const PICO_ANALOG_BOARD                         = 0x00000052
  # unable to configure the Signal Generator
  const PICO_CONFIG_FAIL_AWG                      = 0x00000053
  const PICO_INITIALISE_FPGA                      = 0x00000054
  const PICO_EXTERNAL_FREQUENCY_INVALID           = 0x00000056
  const PICO_CLOCK_CHANGE_ERROR                   = 0x00000057
  const PICO_TRIGGER_AND_EXTERNAL_CLOCK_CLASH     = 0x00000058
  const PICO_PWQ_AND_EXTERNAL_CLOCK_CLASH         = 0x00000059
  const PICO_UNABLE_TO_OPEN_SCALING_FILE          = 0x0000005A

  const PICO_MEMORY_CLOCK_FREQUENCY               = 0x0000005B
  const PICO_I2C_NOT_RESPONDING                   = 0x0000005C

  const PICO_NO_CAPTURES_AVAILABLE                = 0x0000005D
  const PICO_NOT_USED_IN_THIS_CAPTURE_MODE        = 0x0000005E

  const PICO_GET_DATA_ACTIVE                      = 0x00000103

  # used by the PT104 (USB) when connected via the Network Socket
  const PICO_IP_NETWORKED                         = 0x00000104
  const PICO_INVALID_IP_ADDRESS                   = 0x00000105
  const PICO_IPSOCKET_FAILED                      = 0x00000106
  const PICO_IPSOCKET_TIMEDOUT                    = 0x00000107
  const PICO_SETTINGS_FAILED                      = 0x00000108
  const PICO_NETWORK_FAILED                       = 0x00000109
  const PICO_WS2_32_DLL_NOT_LOADED                = 0x0000010A
  const PICO_INVALID_IP_PORT                      = 0x0000010B

  const PICO_COUPLING_NOT_SUPPORTED               = 0x0000010C
  const PICO_BANDWIDTH_NOT_SUPPORTED              = 0x0000010D
  const PICO_INVALID_BANDWIDTH                    = 0x0000010E

  const PICO_AWG_NOT_SUPPORTED                    = 0x0000010F
  const PICO_ETS_NOT_RUNNING                      = 0x00000110
  const PICO_SIG_GEN_WHITENOISE_NOT_SUPPORTED     = 0x00000111
  const PICO_SIG_GEN_WAVETYPE_NOT_SUPPORTED       = 0x00000112

  const PICO_INVALID_DIGITAL_PORT                 = 0x00000113
  const PICO_INVALID_DIGITAL_CHANNEL              = 0x00000114
  const PICO_INVALID_DIGITAL_TRIGGER_DIRECTION    = 0x00000115

  const PICO_SIG_GEN_PRBS_NOT_SUPPORTED           = 0x00000116

  const PICO_ETS_NOT_AVAILABLE_WITH_LOGIC_CHANNELS= 0x00000117

  const PICO_WARNING_REPEAT_VALUE                 = 0x00000118

  const PICO_POWER_SUPPLY_CONNECTED               = 0x00000119
  const PICO_POWER_SUPPLY_NOT_CONNECTED           = 0x0000011A
  const PICO_POWER_SUPPLY_REQUEST_INVALID         = 0x0000011B
  const PICO_POWER_SUPPLY_UNDERVOLTAGE            = 0x000001

  const PICO_CAPTURING_DATA                       = 0x0000011D

  const PICO_USB3_0_DEVICE_NON_USB3_0_PORT        = 0x0000011E

  const PICO_NOT_SUPPORTED_BY_THIS_DEVICE         = 0x0000011F
  const PICO_INVALID_DEVICE_RESOLUTION            = 0x00000120
  const PICO_INVALID_NUMBER_CHANNELS_FOR_RESOLUTION = 0x00000121

  const PICO_CHANNEL_DISABLED_DUE_TO_USB_POWERED  = 0x00000122

  const PICO_SIGGEN_DC_VOLTAGE_NOT_CONFIGURABLE   = 0x00000123

  const PICO_NO_TRIGGER_ENABLED_FOR_TRIGGER_IN_PRE_TRIG= 0x00000124
  const PICO_TRIGGER_WITHIN_PRE_TRIG_NOT_ARMED         = 0x00000125
  const PICO_TRIGGER_WITHIN_PRE_NOT_ALLOWED_WITH_DELAY = 0x00000126
  const PICO_TRIGGER_INDEX_UNAVAILABLE                 = 0x00000127

  const PICO_AWG_CLOCK_FREQUENCY                = 0x00000128
  # there are more than 4 analogue channels with a trigger condition set
  const PICO_TOO_MANY_CHANNELS_IN_USE           = 0x00000129

  const PICO_NULL_CONDITIONS                    = 0x0000012A
  const PICO_DUPLICATE_CONDITION_SOURCE         = 0x0000012B
  const PICO_INVALID_CONDITION_INFO             = 0x0000012C

  const PICO_SETTINGS_READ_FAILED               = 0x0000012D
  const PICO_SETTINGS_WRITE_FAILED              = 0x0000012E

  const PICO_ARGUMENT_OUT_OF_RANGE              = 0x0000012F

  const PICO_HARDWARE_VERSION_NOT_SUPPORTED     = 0x00000130
  const PICO_DIGITAL_HARDWARE_VERSION_NOT_SUPPORTED     = 0x00000131
  const PICO_ANALOGUE_HARDWARE_VERSION_NOT_SUPPORTED      = 0x00000132

  const PICO_UNABLE_TO_CONVERT_TO_RESISTANCE    = 0x00000133
  const PICO_DUPLICATED_CHANNEL                 = 0x00000134

  const PICO_INVALID_RESISTANCE_CONVERSION      = 0x00000135
  const PICO_INVALID_VALUE_IN_MAX_BUFFER        = 0x00000136
  const PICO_INVALID_VALUE_IN_MIN_BUFFER        = 0x00000137

  const PICO_SIGGEN_FREQUENCY_OUT_OF_RANGE      = 0x00000138

  const PICO_EEPROM2_CORRUPT                    = 0x00000139
  const PICO_EEPROM2_FAIL                       = 0x0000013A

  const PICO_DEVICE_TIME_STAMP_RESET            = 0x01000000

  const PICO_WATCHDOGTIMER                      = 0x10000000

  const PICO_IPP_NOT_FOUND                      = 0x10000001
  const PICO_IPP_NO_FUNCTION                    = 0x10000002
  const PICO_IPP_ERROR                          = 0x10000003

  const PICO_SHADOW_CAL_NOT_AVAILABLE           = 0x10000004
  const PICO_SHADOW_CAL_DISABLED                = 0x10000005
  const PICO_SHADOW_CAL_ERROR                   = 0x10000006
  const PICO_SHADOW_CAL_CORRUPT                 = 0x10000007
end # PICO_STATUS

picoscopestatusdict = Dict(
  PICO_STATUS.PICO_OK => "PICO_OK",
  PICO_STATUS.PICO_MAX_UNITS_OPENED => "PICO_MAX_UNITS_OPENED",
  PICO_STATUS.PICO_MEMORY_FAIL => "PICO_MEMORY_FAIL",
  PICO_STATUS.PICO_NOT_FOUND => "PICO_NOT_FOUND",
  PICO_STATUS.PICO_FW_FAIL => "PICO_FW_FAIL",
  PICO_STATUS.PICO_OPEN_OPERATION_IN_PROGRESS => "PICO_OPEN_OPERATION_IN_PROGRESS",
  PICO_STATUS.PICO_OPERATION_FAILED => "PICO_OPERATION_FAILED",
  PICO_STATUS.PICO_NOT_RESPONDING => "PICO_NOT_RESPONDING",
  PICO_STATUS.PICO_CONFIG_FAIL => "PICO_CONFIG_FAIL",
  PICO_STATUS.PICO_KERNEL_DRIVER_TOO_OLD => "PICO_KERNEL_DRIVER_TOO_OLD",
  PICO_STATUS.PICO_EEPROM_CORRUPT => "PICO_EEPROM_CORRUPT",
  PICO_STATUS.PICO_OS_NOT_SUPPORTED => "PICO_OS_NOT_SUPPORTED",
  PICO_STATUS.PICO_INVALID_HANDLE => "PICO_INVALID_HANDLE",
  PICO_STATUS.PICO_INVALID_PARAMETER => "PICO_INVALID_PARAMETER",
  PICO_STATUS.PICO_INVALID_TIMEBASE => "PICO_INVALID_TIMEBASE",
  PICO_STATUS.PICO_INVALID_VOLTAGE_RANGE => "PICO_INVALID_VOLTAGE_RANGE",
  PICO_STATUS.PICO_INVALID_CHANNEL => "PICO_INVALID_CHANNEL",
  PICO_STATUS.PICO_INVALID_TRIGGER_CHANNEL => "PICO_INVALID_TRIGGER_CHANNEL",
  PICO_STATUS.PICO_INVALID_CONDITION_CHANNEL => "PICO_INVALID_CONDITION_CHANNEL",
  PICO_STATUS.PICO_NO_SIGNAL_GENERATOR => "PICO_NO_SIGNAL_GENERATOR",
  PICO_STATUS.PICO_STREAMING_FAILED => "PICO_STREAMING_FAILED",
  PICO_STATUS.PICO_BLOCK_MODE_FAILED => "PICO_BLOCK_MODE_FAILED",
  PICO_STATUS.PICO_NULL_PARAMETER => "PICO_NULL_PARAMETER",
  PICO_STATUS.PICO_ETS_MODE_SET => "PICO_ETS_MODE_SET",
  PICO_STATUS.PICO_DATA_NOT_AVAILABLE => "PICO_DATA_NOT_AVAILABLE",
  PICO_STATUS.PICO_STRING_BUFFER_TOO_SMALL => "PICO_STRING_BUFFER_TOO_SMALL",
  PICO_STATUS.PICO_ETS_NOT_SUPPORTED => "PICO_ETS_NOT_SUPPORTED",
  PICO_STATUS.PICO_AUTO_TRIGGER_TIME_TOO_SHORT => "PICO_AUTO_TRIGGER_TIME_TOO_SHORT",
  PICO_STATUS.PICO_BUFFER_STALL => "PICO_BUFFER_STALL",
  PICO_STATUS.PICO_TOO_MANY_SAMPLES => "PICO_TOO_MANY_SAMPLES",
  PICO_STATUS.PICO_TOO_MANY_SEGMENTS => "PICO_TOO_MANY_SEGMENTS",
  PICO_STATUS.PICO_PULSE_WIDTH_QUALIFIER => "PICO_PULSE_WIDTH_QUALIFIER",
  PICO_STATUS.PICO_DELAY => "PICO_DELAY",
  PICO_STATUS.PICO_SOURCE_DETAILS => "PICO_SOURCE_DETAILS",
  PICO_STATUS.PICO_CONDITIONS => "PICO_CONDITIONS",
  PICO_STATUS.PICO_USER_CALLBACK => "PICO_USER_CALLBACK",
  PICO_STATUS.PICO_DEVICE_SAMPLING => "PICO_DEVICE_SAMPLING",
  PICO_STATUS.PICO_NO_SAMPLES_AVAILABLE => "PICO_NO_SAMPLES_AVAILABLE",
  PICO_STATUS.PICO_SEGMENT_OUT_OF_RANGE => "PICO_SEGMENT_OUT_OF_RANGE",
  PICO_STATUS.PICO_BUSY => "PICO_BUSY",
  PICO_STATUS.PICO_STARTINDEX_INVALID => "PICO_STARTINDEX_INVALID",
  PICO_STATUS.PICO_INVALID_INFO => "PICO_INVALID_INFO",
  PICO_STATUS.PICO_INFO_UNAVAILABLE => "PICO_INFO_UNAVAILABLE",
  PICO_STATUS.PICO_INVALID_SAMPLE_INTERVAL => "PICO_INVALID_SAMPLE_INTERVAL",
  PICO_STATUS.PICO_TRIGGER_ERROR => "PICO_TRIGGER_ERROR",
  PICO_STATUS.PICO_MEMORY => "PICO_MEMORY",
  PICO_STATUS.PICO_SIG_GEN_PARAM => "PICO_SIG_GEN_PARAM",
  PICO_STATUS.PICO_SHOTS_SWEEPS_WARNING => "PICO_SHOTS_SWEEPS_WARNING",
  PICO_STATUS.PICO_SIGGEN_TRIGGER_SOURCE => "PICO_SIGGEN_TRIGGER_SOURCE",
  PICO_STATUS.PICO_AUX_OUTPUT_CONFLICT => "PICO_AUX_OUTPUT_CONFLICT",
  PICO_STATUS.PICO_AUX_OUTPUT_ETS_CONFLICT => "PICO_AUX_OUTPUT_ETS_CONFLICT",
  PICO_STATUS.PICO_WARNING_EXT_THRESHOLD_CONFLICT => "PICO_WARNING_EXT_THRESHOLD_CONFLICT",
  PICO_STATUS.PICO_WARNING_AUX_OUTPUT_CONFLICT => "PICO_WARNING_AUX_OUTPUT_CONFLICT",
  PICO_STATUS.PICO_SIGGEN_OUTPUT_OVER_VOLTAGE => "PICO_SIGGEN_OUTPUT_OVER_VOLTAGE",
  PICO_STATUS.PICO_DELAY_NULL => "PICO_DELAY_NULL",
  PICO_STATUS.PICO_INVALID_BUFFER => "PICO_INVALID_BUFFER",
  PICO_STATUS.PICO_SIGGEN_OFFSET_VOLTAGE => "PICO_SIGGEN_OFFSET_VOLTAGE",
  PICO_STATUS.PICO_SIGGEN_PK_TO_PK => "PICO_SIGGEN_PK_TO_PK",
  PICO_STATUS.PICO_CANCELLED => "PICO_CANCELLED",
  PICO_STATUS.PICO_SEGMENT_NOT_USED => "PICO_SEGMENT_NOT_USED",
  PICO_STATUS.PICO_INVALID_CALL => "PICO_INVALID_CALL",
  PICO_STATUS.PICO_GET_VALUES_INTERRUPTED => "PICO_GET_VALUES_INTERRUPTED",
  PICO_STATUS.PICO_NOT_USED => "PICO_NOT_USED",
  PICO_STATUS.PICO_INVALID_SAMPLERATIO => "PICO_INVALID_SAMPLERATIO",
  PICO_STATUS.PICO_INVALID_STATE => "PICO_INVALID_STATE",
  PICO_STATUS.PICO_NOT_ENOUGH_SEGMENTS => "PICO_NOT_ENOUGH_SEGMENTS",
  PICO_STATUS.PICO_DRIVER_FUNCTION => "PICO_DRIVER_FUNCTION",
  PICO_STATUS.PICO_RESERVED => "PICO_RESERVED",
  PICO_STATUS.PICO_INVALID_COUPLING => "PICO_INVALID_COUPLING",
  PICO_STATUS.PICO_BUFFERS_NOT_SET => "PICO_BUFFERS_NOT_SET",
  PICO_STATUS.PICO_RATIO_MODE_NOT_SUPPORTED => "PICO_RATIO_MODE_NOT_SUPPORTED",
  PICO_STATUS.PICO_RAPID_NOT_SUPPORT_AGGREGATION => "PICO_RAPID_NOT_SUPPORT_AGGREGATION",
  PICO_STATUS.PICO_INVALID_TRIGGER_PROPERTY => "PICO_INVALID_TRIGGER_PROPERTY",
  PICO_STATUS.PICO_RESISTANCE_AND_PROBE_NOT_ALLOWED => "PICO_RESISTANCE_AND_PROBE_NOT_ALLOWED",
  PICO_STATUS.PICO_POWER_FAILED => "PICO_POWER_FAILED",
  PICO_STATUS.PICO_SIGGEN_WAVEFORM_SETUP_FAILED => "PICO_SIGGEN_WAVEFORM_SETUP_FAILED",
  PICO_STATUS.PICO_FPGA_FAIL => "PICO_FPGA_FAIL",
  PICO_STATUS.PICO_POWER_MANAGER => "PICO_POWER_MANAGER",
  PICO_STATUS.PICO_INVALID_ANALOGUE_OFFSET => "PICO_INVALID_ANALOGUE_OFFSET",
  PICO_STATUS.PICO_PLL_LOCK_FAILED => "PICO_PLL_LOCK_FAILED",
  PICO_STATUS.PICO_ANALOG_BOARD => "PICO_ANALOG_BOARD",
  PICO_STATUS.PICO_CONFIG_FAIL_AWG => "PICO_CONFIG_FAIL_AWG",
  PICO_STATUS.PICO_INITIALISE_FPGA => "PICO_INITIALISE_FPGA",
  PICO_STATUS.PICO_EXTERNAL_FREQUENCY_INVALID => "PICO_EXTERNAL_FREQUENCY_INVALID",
  PICO_STATUS.PICO_CLOCK_CHANGE_ERROR => "PICO_CLOCK_CHANGE_ERROR",
  PICO_STATUS.PICO_TRIGGER_AND_EXTERNAL_CLOCK_CLASH => "PICO_TRIGGER_AND_EXTERNAL_CLOCK_CLASH",
  PICO_STATUS.PICO_PWQ_AND_EXTERNAL_CLOCK_CLASH => "PICO_PWQ_AND_EXTERNAL_CLOCK_CLASH",
  PICO_STATUS.PICO_UNABLE_TO_OPEN_SCALING_FILE => "PICO_UNABLE_TO_OPEN_SCALING_FILE",
  PICO_STATUS.PICO_MEMORY_CLOCK_FREQUENCY => "PICO_MEMORY_CLOCK_FREQUENCY",
  PICO_STATUS.PICO_I2C_NOT_RESPONDING => "PICO_I2C_NOT_RESPONDING",
  PICO_STATUS.PICO_NO_CAPTURES_AVAILABLE => "PICO_NO_CAPTURES_AVAILABLE",
  PICO_STATUS.PICO_NOT_USED_IN_THIS_CAPTURE_MODE => "PICO_NOT_USED_IN_THIS_CAPTURE_MODE",
  PICO_STATUS.PICO_GET_DATA_ACTIVE => "PICO_GET_DATA_ACTIVE",
  PICO_STATUS.PICO_IP_NETWORKED => "PICO_IP_NETWORKED",
  PICO_STATUS.PICO_INVALID_IP_ADDRESS => "PICO_INVALID_IP_ADDRESS",
  PICO_STATUS.PICO_IPSOCKET_FAILED => "PICO_IPSOCKET_FAILED",
  PICO_STATUS.PICO_IPSOCKET_TIMEDOUT => "PICO_IPSOCKET_TIMEDOUT",
  PICO_STATUS.PICO_SETTINGS_FAILED => "PICO_SETTINGS_FAILED",
  PICO_STATUS.PICO_NETWORK_FAILED => "PICO_NETWORK_FAILED",
  PICO_STATUS.PICO_WS2_32_DLL_NOT_LOADED => "PICO_WS2_32_DLL_NOT_LOADED",
  PICO_STATUS.PICO_INVALID_IP_PORT => "PICO_INVALID_IP_PORT",
  PICO_STATUS.PICO_COUPLING_NOT_SUPPORTED => "PICO_COUPLING_NOT_SUPPORTED",
  PICO_STATUS.PICO_BANDWIDTH_NOT_SUPPORTED => "PICO_BANDWIDTH_NOT_SUPPORTED",
  PICO_STATUS.PICO_INVALID_BANDWIDTH => "PICO_INVALID_BANDWIDTH",
  PICO_STATUS.PICO_AWG_NOT_SUPPORTED => "PICO_AWG_NOT_SUPPORTED",
  PICO_STATUS.PICO_ETS_NOT_RUNNING => "PICO_ETS_NOT_RUNNING",
  PICO_STATUS.PICO_SIG_GEN_WHITENOISE_NOT_SUPPORTED => "PICO_SIG_GEN_WHITENOISE_NOT_SUPPORTED",
  PICO_STATUS.PICO_SIG_GEN_WAVETYPE_NOT_SUPPORTED => "PICO_SIG_GEN_WAVETYPE_NOT_SUPPORTED",
  PICO_STATUS.PICO_INVALID_DIGITAL_PORT => "PICO_INVALID_DIGITAL_PORT",
  PICO_STATUS.PICO_INVALID_DIGITAL_CHANNEL => "PICO_INVALID_DIGITAL_CHANNEL",
  PICO_STATUS.PICO_INVALID_DIGITAL_TRIGGER_DIRECTION => "PICO_INVALID_DIGITAL_TRIGGER_DIRECTION",
  PICO_STATUS.PICO_SIG_GEN_PRBS_NOT_SUPPORTED => "PICO_SIG_GEN_PRBS_NOT_SUPPORTED",
  PICO_STATUS.PICO_ETS_NOT_AVAILABLE_WITH_LOGIC_CHANNELS => "PICO_ETS_NOT_AVAILABLE_WITH_LOGIC_CHANNELS",
  PICO_STATUS.PICO_WARNING_REPEAT_VALUE => "PICO_WARNING_REPEAT_VALUE",
  PICO_STATUS.PICO_POWER_SUPPLY_CONNECTED => "PICO_POWER_SUPPLY_CONNECTED",
  PICO_STATUS.PICO_POWER_SUPPLY_NOT_CONNECTED => "PICO_POWER_SUPPLY_NOT_CONNECTED",
  PICO_STATUS.PICO_POWER_SUPPLY_REQUEST_INVALID => "PICO_POWER_SUPPLY_REQUEST_INVALID",
  PICO_STATUS.PICO_POWER_SUPPLY_UNDERVOLTAGE => "PICO_POWER_SUPPLY_UNDERVOLTAGE",
  PICO_STATUS.PICO_CAPTURING_DATA => "PICO_CAPTURING_DATA",
  PICO_STATUS.PICO_USB3_0_DEVICE_NON_USB3_0_PORT => "PICO_USB3_0_DEVICE_NON_USB3_0_PORT",
  PICO_STATUS.PICO_NOT_SUPPORTED_BY_THIS_DEVICE => "PICO_NOT_SUPPORTED_BY_THIS_DEVICE",
  PICO_STATUS.PICO_INVALID_DEVICE_RESOLUTION => "PICO_INVALID_DEVICE_RESOLUTION",
  PICO_STATUS.PICO_INVALID_NUMBER_CHANNELS_FOR_RESOLUTION => "PICO_INVALID_NUMBER_CHANNELS_FOR_RESOLUTION",
  PICO_STATUS.PICO_CHANNEL_DISABLED_DUE_TO_USB_POWERED => "PICO_CHANNEL_DISABLED_DUE_TO_USB_POWERED",
  PICO_STATUS.PICO_SIGGEN_DC_VOLTAGE_NOT_CONFIGURABLE => "PICO_SIGGEN_DC_VOLTAGE_NOT_CONFIGURABLE",
  PICO_STATUS.PICO_NO_TRIGGER_ENABLED_FOR_TRIGGER_IN_PRE_TRIG => "PICO_NO_TRIGGER_ENABLED_FOR_TRIGGER_IN_PRE_TRIG",
  PICO_STATUS.PICO_TRIGGER_WITHIN_PRE_TRIG_NOT_ARMED => "PICO_TRIGGER_WITHIN_PRE_TRIG_NOT_ARMED",
  PICO_STATUS.PICO_TRIGGER_WITHIN_PRE_NOT_ALLOWED_WITH_DELAY => "PICO_TRIGGER_WITHIN_PRE_NOT_ALLOWED_WITH_DELAY",
  PICO_STATUS.PICO_TRIGGER_INDEX_UNAVAILABLE => "PICO_TRIGGER_INDEX_UNAVAILABLE",
  PICO_STATUS.PICO_AWG_CLOCK_FREQUENCY => "PICO_AWG_CLOCK_FREQUENCY",
  PICO_STATUS.PICO_TOO_MANY_CHANNELS_IN_USE => "PICO_TOO_MANY_CHANNELS_IN_USE",
  PICO_STATUS.PICO_NULL_CONDITIONS => "PICO_NULL_CONDITIONS",
  PICO_STATUS.PICO_DUPLICATE_CONDITION_SOURCE => "PICO_DUPLICATE_CONDITION_SOURCE",
  PICO_STATUS.PICO_INVALID_CONDITION_INFO => "PICO_INVALID_CONDITION_INFO",
  PICO_STATUS.PICO_SETTINGS_READ_FAILED => "PICO_SETTINGS_READ_FAILED",
  PICO_STATUS.PICO_SETTINGS_WRITE_FAILED => "PICO_SETTINGS_WRITE_FAILED",
  PICO_STATUS.PICO_ARGUMENT_OUT_OF_RANGE => "PICO_ARGUMENT_OUT_OF_RANGE",
  PICO_STATUS.PICO_HARDWARE_VERSION_NOT_SUPPORTED => "PICO_HARDWARE_VERSION_NOT_SUPPORTED",
  PICO_STATUS.PICO_DIGITAL_HARDWARE_VERSION_NOT_SUPPORTED => "PICO_DIGITAL_HARDWARE_VERSION_NOT_SUPPORTED",
  PICO_STATUS.PICO_ANALOGUE_HARDWARE_VERSION_NOT_SUPPORTED => "PICO_ANALOGUE_HARDWARE_VERSION_NOT_SUPPORTED",
  PICO_STATUS.PICO_UNABLE_TO_CONVERT_TO_RESISTANCE => "PICO_UNABLE_TO_CONVERT_TO_RESISTANCE",
  PICO_STATUS.PICO_DUPLICATED_CHANNEL => "PICO_DUPLICATED_CHANNEL",
  PICO_STATUS.PICO_INVALID_RESISTANCE_CONVERSION => "PICO_INVALID_RESISTANCE_CONVERSION",
  PICO_STATUS.PICO_INVALID_VALUE_IN_MAX_BUFFER => "PICO_INVALID_VALUE_IN_MAX_BUFFER",
  PICO_STATUS.PICO_INVALID_VALUE_IN_MIN_BUFFER => "PICO_INVALID_VALUE_IN_MIN_BUFFER",
  PICO_STATUS.PICO_SIGGEN_FREQUENCY_OUT_OF_RANGE => "PICO_SIGGEN_FREQUENCY_OUT_OF_RANGE",
  PICO_STATUS.PICO_EEPROM2_CORRUPT => "PICO_EEPROM2_CORRUPT",
  PICO_STATUS.PICO_EEPROM2_FAIL => "PICO_EEPROM2_FAIL",
  PICO_STATUS.PICO_DEVICE_TIME_STAMP_RESET => "PICO_DEVICE_TIME_STAMP_RESET",
  PICO_STATUS.PICO_WATCHDOGTIMER => "PICO_WATCHDOGTIMER",
  PICO_STATUS.PICO_IPP_NOT_FOUND => "PICO_IPP_NOT_FOUND",
  PICO_STATUS.PICO_IPP_NO_FUNCTION => "PICO_IPP_NO_FUNCTION",
  PICO_STATUS.PICO_IPP_ERROR => "PICO_IPP_ERROR",
  PICO_STATUS.PICO_SHADOW_CAL_NOT_AVAILABLE => "PICO_SHADOW_CAL_NOT_AVAILABLE",
  PICO_STATUS.PICO_SHADOW_CAL_DISABLED => "PICO_SHADOW_CAL_DISABLED",
  PICO_STATUS.PICO_SHADOW_CAL_ERROR => "PICO_SHADOW_CAL_ERROR",
  PICO_STATUS.PICO_SHADOW_CAL_CORRUPT => "PICO_SHADOW_CAL_CORRUPT")
# end Dict

function Base.showerror(io::IO, e::PicoScopeError)
  errortext = get(picoscopestatusdict,UInt32(e.picostatus),"Code Not Found")
  print(io, "PicoScopeError: ",errortext)
end

function checkstatus(picostatus::PicoStatus)
  if picostatus != PICO_STATUS.PICO_OK
    throw(PicoScopeError(picostatus))
  end
  return nothing
end


text:
using NewtonsMethod
using Test

@testset "NewtonsMethod.jl" begin

# several @test for the root of a known function, given the f and analytical f' derivatives
f(x) = x - 10
f′(x)= 1
@test newtonroot(f,f′;x₀ = 0.0) == 10.0

f(x) = x-cos(x)
f′(x)= 1+sin(x)
@test newtonroot(f,f′;x₀ = 0.0) == 0.7390851332151607

f(x) = (x+5)^3
f′(x)= 3*(x+5)^2
@test newtonroot(f,f′;x₀ = 0.0) == -4.999999866018182

# tests of those roots using the automatic differentiation version of the function
f(x) = (x-1)^3
@test newtonroot(f;x₀=0.0) == 0.9999998643434097

f(x) = (x+1)^2
@test newtonroot(f;x₀=0.0) == -0.9999999403953552

f(x) = x^3 + x^2 + x - 1
@test newtonroot(f;x₀=0.0) == 0.5436890126920766

# test of finding those roots with a BigFloat and not just a Float64
f(x) = x - BigFloat(sqrt(5))
@test newtonroot(f;x₀ = 0.0) == BigFloat(sqrt(5))

f(x) =x-BigFloat(pi)
@test newtonroot(f;x₀ = 0.0) == BigFloat(pi)

# test of non-convergence for a function without a root (e.g. f(x)=2+x^2)
f(x) = x^2 + 2
@test newtonroot(f;x₀ = 1.0) == nothing

# test to ensure that the maxiter is working (e.g. what happens if you call maxiter = 5)
f(x) = (x-1)^3
f′(x)= 3*(x-1)^2
@test newtonroot(f,f′;x₀ = 0.0,maxiter = 5) == nothing

f(x) = (x-6)^6
@test newtonroot(f;x₀ = 0.0, maxiter = 10) == nothing

# test to ensure that tol is working
f(x) = (x-1)^3
f′(x)= 3*(x-1)^2
@test newtonroot(f,f′;x₀ = 0.0,tol = 1E-20) == 0.9999999999999999

f(x) = (x-6)^6
@test newtonroot(f;x₀ = 0.0,tol = 1E-3) == 5.995101279575065

end

ext: jl


text:
"""
    eqAPOstring(filterType::Symbol, f, dbGain, Q)

Convert a three-parameter filter to a string in Equalizer APO
configuration file format.

As `filterType` use:
- `:PK` for peaking filter
- `:LS` for low shelf filter
- `:HS` for high shelf filter

Parameters are the center frequency `f` in Hz, the Gain `dbGain` in dB and the
quality factor `Q`.
"""
function eqAPOstring(filterType::Symbol, f, dbGain, Q)
    if filterType in [:PK, :LS, :HS]
        return string("Filter: ON ", filterType, " Fc ", f, " Hz Gain ",
        dbGain, " dB Q ", Q, "\n")
    else
        error("three-argument filterType not recognized")
    end
end

"""
    eqAPOstring(filterType::Symbol, f, Q)

Convert a two-parameter filter to a
string in Equalizer APO configuration file format.

As `filterType` use:
- `:LP` for lowpass filter
- `:HP` for high pass filter
- `:BP` for band pass filter
- `:NO` for notch filter
- `:AP` for all pass filter

Parameters are the frequency `f` in Hz and the quality factor `Q`.
"""
function eqAPOstring(filterType::Symbol, f, Q)
    if filterType in [:LP, :HP, :BP, :NO, :AP]
        return string("Filter: ON ", filterType, " Fc ", f, " Hz Q ", Q, "\n")
    else
        error("two-argument filterType not recognized")
    end
end

"""
    eqAPOstring(filterType::Symbol, param)

Covert a gain or delay filter to a string in Equalizer APO configuration file format.

As `filterType` use:
- `:G` for gain filter with gain in dB
- `:D` for delay filter with delay in ms
- `:Ds` for delay filter with delay in samples.
"""
function eqAPOstring(filterType::Symbol, param)
    if filterType == :G
        return string("Preamp: ", param, " dB\n")
    elseif filterType == :D
        return string("Delay: ", param, " ms\n")
    elseif filterType == :Ds
        return string("Delay: ", param, " samples\n")
    else
        error("single-argument filterType not recognized")
    end
end

function eqAPOstring(x::Tuple{Symbol, Vararg})
    eqAPOstring(x...)
end

"""
    eqAPOstring(x::Array{T} where {T <: Tuple{Symbol, Vararg}})

Convert an array of filters in a tuple format to a string in
Equalizer APO configuration file format.

The tuples in the array shall constructed according to:

`([:G|:D|:Ds|:LP|:HP|:BP|:NO|:AP|:PK|:LS|:HS], f, dbGain, Q)`

Depending on the filter please omit the unneeded arguments. See other methods of
[`eqAPOstring`](@ref) for details.
"""
function eqAPOstring(x::Array{T} where {T <: Tuple{Symbol, Vararg}})
    biquadStrings = [eqAPOstring(x[i]) for i in 1:length(x)]
    string(biquadStrings...)
end

"""
    eqAPOstring(x::FilterCoefficients)

Convert the given DSP.jl Filter to a
string in Equalizer APO configuration file format.

The conversion uses second order sections and spreads the gain evenly among all
biquads.
"""
function eqAPOstring(x::FilterCoefficients)
    xsos = SecondOrderSections(x)
    biquads = xsos.biquads
    n = length(biquads)
    gain = xsos.g^(1/n)
    output = string()
    for i in eachindex(biquads)
        currentBiquad = biquads[i]
        output *= string("Filter: ON IIR Order 2 Coefficients ",
        currentBiquad.b0, " ", currentBiquad.b1, " ", currentBiquad.b2, " 1 ",
        currentBiquad.a1, " ", currentBiquad.a2, "\n")
    end
    output
end


text:
abstract JacobianParameters{T}

immutable JacobianParametersUser{T} <: JacobianParameters{T}
    J::Function
end

immutable JacobianParametersAD{T, FT} <: JacobianParameters{T}
    ϵ::T
    Fparams::FT
end

immutable JacobianParametersFD{T, FT} <: JacobianParameters{T}
    ϵ::T
    Fparams::FT
    f1::Vector{T}
    f2::Vector{T}
    e::Vector{T}
    tx::Vector{T}
end

function computeJacobian{T}(x::Vector{T}, J::Matrix{T}, params::JacobianParametersUser{T})
    params.J(x, J)
end

function computeJacobian{T}(x::Vector{T}, J::Matrix{T}, params::JacobianParametersFD{T})
    @assert length(x) == size(J, 1) == size(J, 2)

    local ϵⱼ::T

    for j in 1:length(x)
        ϵⱼ = params.ϵ * x[j] + params.ϵ
        fill!(params.e, 0.)
        params.e[j] = 1.
        simd_waxpy!(params.tx, -ϵⱼ, params.e, x)
        function_stages!(params.tx, params.f1, params.Fparams)
        simd_waxpy!(params.tx, +ϵⱼ, params.e, x)
        function_stages!(params.tx, params.f2, params.Fparams)
        for i in 1:length(x)
            J[i,j] = (params.f2[i]-params.f1[i])/(2ϵⱼ)
        end
    end
end

# TODO (reactivate)
# function computeJacobianFD{T}(x::Vector{T}, J::Matrix{T}, F::Function, Fparams, ϵ::T)
#     local f1::Vector{T} = zeros(T, length(x))
#     local f2::Vector{T} = zeros(T, length(x))
#     local e::Vector{T}  = zeros(T, length(x))
#     local tx::Vector{T} = zeros(T, length(x))
#
#     computeJacobianFD(x, J, F, Fparams, ϵ, f1, f2, e, tx)
# end

function computeJacobian{T}(x::Vector{T}, J::Matrix{T}, Jparams::JacobianParametersAD{T})
    error("computeJacobian() with automatic differentiation not implemented, yet!")
end

function getJacobianParameters(J, Fparams, ϵ, T, n, autodiff)
    if J == nothing
        if autodiff
            Jparams = JacobianParametersAD{T, typeof(Fparams)}(ϵ, Fparams)
        else
            f1 = zeros(T, n)
            f2 = zeros(T, n)
            e  = zeros(T, n)
            tx = zeros(T, n)
            Jparams = JacobianParametersFD{T, typeof(Fparams)}(ϵ, Fparams, f1, f2, e, tx)
        end
    else
        @assert typeof(J) <: Function
        JacobianParametersUser{T}(J)
    end
    return Jparams
end


text:
@testset "Cycle Basis" begin

    function evaluate(x,y)
        x_sorted = sort(sort.(x))
        y_sorted = sort(sort.(y))
        @test x_sorted == y_sorted
    end

    # No Edges
    ex = Graph(1)
    expected_cyclebasis = Array{Int64,1}[]
    @testset "no edges" for g in testgraphs(ex)
        ex_cyclebasis = @inferred cycle_basis(g)
        @test isempty(ex_cyclebasis)
    end

    # Only one self-edge
    elist = [(1,1)]
    ex = Graph(SimpleEdge.(elist))
    expected_cyclebasis = Array{Int64,1}[[1]]
    @testset "one self-edge" for g in testgraphs(ex)
        ex_cyclebasis = cycle_basis(g)
        evaluate(ex_cyclebasis,expected_cyclebasis)
    end

    # Graph with one cycle
    elist = [(1,2),(2,3),(3,4),(4,1),(1,5)]
    ex = Graph(SimpleEdge.(elist))
    expected_cyclebasis = Array{Int64,1}[
        [1,2,3,4] ]
    @testset "one cycle" for g in testgraphs(ex)
        ex_cyclebasis = cycle_basis(g)
        evaluate(ex_cyclebasis,expected_cyclebasis)
    end

    # Graph with 2 of 3 cycles forming a basis
    elist = [(1,2),(1,3),(2,3),(2,4),(3,4)]
    ex = Graph(SimpleEdge.(elist))
    expected_cyclebasis = Array{Int64,1}[
        [2,3,4],
        [2,1,3] ]
    @testset "2 of 3 cycles w/ basis" for g in testgraphs(ex)
        ex_cyclebasis = cycle_basis(g)
        evaluate(ex_cyclebasis,expected_cyclebasis)
    end

    # Testing root argument
    elist = [(1,2),(1,3),(2,3),(2,4),(3,4),(1,5),(5,6),(6,4)]
    ex = Graph(SimpleEdge.(elist))
    expected_cyclebasis = Array{Int64,1}[
        [2, 4, 3],
        [1, 5, 6, 4, 3],
        [1, 2, 3] ]
    @testset "root argument" for g in testgraphs(ex)
        ex_cyclebasis = @inferred cycle_basis(g,3)
        evaluate(ex_cyclebasis,expected_cyclebasis)
    end

    @testset "two isolated cycles" begin
        ex = blockdiag(cycle_graph(3), cycle_graph(4))
        expected_cyclebasis = [[1, 2, 3], [4, 5, 6, 7]]
        for g in testgraphs(ex)
            found_cyclebasis = @inferred cycle_basis(g)
            evaluate(expected_cyclebasis, found_cyclebasis)
        end
    end
end


text:
type class_nlp_cache
    # min f(x)
    # a(x) = 0
    # x >= 0
    n::Int64
    m::Int64
    val_c::Float64
    val_a::Array{Float64,1}
    val_jac_a::SparseMatrixCSC{Float64,Int64}
    val_hesslag_prod::SparseMatrixCSC{Float64,Int64}
    val_gradlag::Array{Float64,1}
    val_gradc::Array{Float64,1}
    val_b::Array{Float64,1}

    function class_nlp_cache()
        return new();
    end
end

function update_nlp_cache!(nlp_vals::class_nlp_cache, nlp_eval::internal_AbstractNLPEvaluator, vars::class_variables)
    try
        nlp_vals.n = n(nlp_eval)
        nlp_vals.m = m(nlp_eval)

        val_x_scaled = x_scaled(vars);
        val_y_scaled = y_scaled(vars);

        start_advanced_timer("Function_evaluation")

        nlp_vals.val_c = internal_eval_c( nlp_eval, val_x_scaled )
        nlp_vals.val_a = internal_eval_a( nlp_eval, val_x_scaled )
        nlp_vals.val_jac_a = internal_eval_jac_a( nlp_eval, val_x_scaled )
        nlp_vals.val_hesslag_prod = internal_eval_hesslag_prod( nlp_eval, val_x_scaled, val_y_scaled )
        nlp_vals.val_gradlag = internal_eval_gradlag( nlp_eval, val_x_scaled, val_y_scaled )
        nlp_vals.val_gradc = internal_eval_gradc( nlp_eval, val_x_scaled )
        nlp_vals.val_b = internal_eval_b( nlp_eval, val_x_scaled )

        pause_advanced_timer("Function_evaluation")
    catch e
        println("class_nlp_cache/update_nlp_cache!")
        throw(e)
    end
end

max_forks_repo_name: ohinder/Everest


text:
"A generic wrapper around `wasm_XXX_vec_t`"
mutable struct WasmVec{T,S} <: AbstractVector{S}
    size::Csize_t
    data::Ptr{S}
end

wasm_vec_delete(wasm_vec::WasmVec{T,S}) where {T,S} = _get_delete_function(T)(wasm_vec)

function WasmVec{T,S}(vector::Vector{S} = S[]) where {T,S}
    vec_size = length(vector)

    wasm_vec = WasmVec{T,S}(0, C_NULL)
    vec_uninitialized = _get_uninitialized_function(T)

    vec_uninitialized(wasm_vec, vec_size)
    src_ptr = pointer(vector)

    GC.@preserve vector unsafe_copyto!(wasm_vec.data, src_ptr, vec_size)

    finalizer(wasm_vec_delete, wasm_vec)
end

_get_delete_function(T) =
    getproperty(LibWasmer, Symbol(string(nameof(T))[1:end-6] * "_vec_delete"))
_get_uninitialized_function(T) =
    getproperty(LibWasmer, Symbol(string(nameof(T))[1:end-6] * "_vec_new_uninitialized"))

WasmVec(base_type::Type) = WasmVec(base_type[])
function WasmVec(vec::Vector{S}) where {S}
    vec_type = _get_wasm_vec_name(S)
    WasmVec{vec_type,S}(vec)
end

WasmPtrVec(base_type::Type) = WasmPtrVec(Ptr{base_type}[])
function WasmPtrVec(vec::Vector{Ptr{S}}) where {S}
    vec_type = _get_wasm_vec_name(S)
    WasmVec{vec_type,Ptr{S}}(vec)
end

_get_wasm_vec_name(::Type{Cchar}) = wasm_byte_vec_t
_get_wasm_vec_name(::Type{UInt8}) = wasm_byte_vec_t
function _get_wasm_vec_name(type::Type)
    @assert parentmodule(type) == LibWasmer "$type should be a LibWasm type"
    type_name = string(nameof(type)) # "wasm_XXX_t"
    vec_type_sym = Symbol(replace(type_name, r"_t$" => "_vec_t")) # :wasm_XXX_vec_t
    getproperty(LibWasmer, vec_type_sym)
end

Base.IndexStyle(::Type{WasmVec}) = IndexLinear()
Base.length(vec::WasmVec) = vec.size
Base.size(vec::WasmVec) = (length(vec),)
function Base.getindex(vec::WasmVec, i::Int)
    @assert 1 <= i <= length(vec) BoundsError(vec, i)
    unsafe_load(vec.data, i)
end
function Base.setindex!(vec::WasmVec{T,S}, v::S, i::Int) where {T,S}
    @assert 1 <= i <= length(vec) BoundsError(vec, i)
    elsize = sizeof(S)

    ref = Ref(v)
    src_ptr = Base.unsafe_convert(Ptr{S}, ref)
    dest_ptr = Base.unsafe_convert(Ptr{S}, vec.data + elsize * (i - 1))

    GC.@preserve ref unsafe_copyto!(dest_ptr, src_ptr, 1)

    v
end

Base.unsafe_convert(::Type{Ptr{T}}, vec::WasmVec{T,S}) where {T,S} =
    Base.unsafe_convert(Ptr{T}, pointer_from_objref(vec))
Base.unsafe_convert(::Type{Ptr{S}}, vec::WasmVec{T,S}) where {T,S} = vec.data

const WasmByteVec = WasmVec{wasm_byte_vec_t,UInt8}
const WasmName = WasmByteVec


text:
include("differentiation.jl")

# Ambiguity detection is so much slower on Julia 1.6.0-DEV.430, so this reduces
# the number of packages involved to a reasonable minimum
using LinearAlgebra, Manifolds, ManifoldsBase, StaticArrays, Statistics, StatsBase

function our_base_ambiguities()
    ambigs = Test.detect_ambiguities(Base)
    modules_we_care_about =
        [Base, LinearAlgebra, Manifolds, ManifoldsBase, StaticArrays, Statistics, StatsBase]
    our_ambigs = filter(ambigs) do (m1, m2)
        we_care = m1.module in modules_we_care_about && m2.module in modules_we_care_about
        return we_care && (m1.module === Manifolds || m2.module === Manifolds)
    end
    return our_ambigs
end

(VERSION >= v"1.1") && @testset "Ambiguities" begin
    # TODO: reduce the number of ambiguities
    if VERSION >= v"1.6-DEV"
        @test length(Test.detect_ambiguities(ManifoldsBase)) <= 4
        @test length(Test.detect_ambiguities(Manifolds)) <= 102
        @test length(our_base_ambiguities()) <= 4
    else
        @test length(Test.detect_ambiguities(ManifoldsBase)) <= 17
        @test length(Test.detect_ambiguities(Manifolds)) == 0
        @test length(our_base_ambiguities()) <= 24
    end
end

include("utils.jl")

@info "Manifolds.jl Test settings:\n\n" *
      "Testing Float32:  $(TEST_FLOAT32)\n" *
      "Testing Double64: $(TEST_DOUBLE64)\n" *
      "Testing Static:   $(TEST_STATIC_SIZED)\n"

include("groups/group_utils.jl")
include("sized_abstract_array.jl")
include("errors.jl")
include("notation.jl")
# starting with tests of simple manifolds
include("centered_matrices.jl")
include("circle.jl")
include("cholesky_space.jl")
include("elliptope.jl")
include("euclidean.jl")
include("fixed_rank.jl")
include("generalized_grassmann.jl")
include("generalized_stiefel.jl")
include("grassmann.jl")
include("hyperbolic.jl")
include("multinomial_doubly_stochastic.jl")
include("multinomial_symmetric.jl")
include("positive_numbers.jl")
include("probability_simplex.jl")
include("projective_space.jl")
include("rotations.jl")
include("skewsymmetric.jl")
include("spectrahedron.jl")
include("sphere.jl")
include("sphere_symmetric_matrices.jl")
include("stiefel.jl")
include("symmetric.jl")
include("symmetric_positive_definite.jl")
include("symmetric_positive_semidefinite_fixed_rank.jl")

include("multinomial_matrices.jl")
include("oblique.jl")
include("torus.jl")

#meta manifolds
include("product_manifold.jl")
include("power_manifold.jl")
include("vector_bundle.jl")
include("graph.jl")

include("metric.jl")
include("statistics.jl")

# Lie groups and actions
include("groups/groups_general.jl")
include("groups/array_manifold.jl")
include("groups/circle_group.jl")
include("groups/translation_group.jl")
include("groups/special_orthogonal.jl")
include("groups/product_group.jl")
include("groups/semidirect_product_group.jl")
include("groups/special_euclidean.jl")
include("groups/group_operation_action.jl")
include("groups/rotation_action.jl")
include("groups/translation_action.jl")
include("groups/metric.jl")

include("recipes.jl")


text:
using DataDeps

register(DataDep(
  "parkinsons",
  "http://archive.ics.uci.edu/ml/datasets/Parkinsons",
  "http://archive.ics.uci.edu/ml/machine-learning-databases/parkinsons/parkinsons.data",
  "a36116c2deac07895b79ce97a2f99a1b3720ac4892995ff5c3b9ccb397ed2bc5",
  post_fetch_method=(path -> begin
    UCIData.process_dataset(path,
        target_index=18,
        feature_indices=[2:17; 19:23],
        id_indices=1,
        skipto=2,
    )
  end),
))

max_stars_repo_name: JackDunnNZ/uci-data

max_issues_repo_name: JackDunnNZ/uci-data

max_forks_repo_name: JackDunnNZ/uci-data


text:
"""
    weval(e)

Evaluate a Wolfram expression in Mathematica.
"""
weval(e) = MathLink.weval(buildexpr(e)) |> getexpr

"""
    @importsymbol Get, N, Plot

Import Mathematica symbols as normal Julia functions.

Note: This will eagerly evaluate the function.
Some expressions involving evaluation control (like `Hold`) may not work as expected.
"""
macro importsymbol(arg)
    if arg isa Symbol
        list = [arg]
    elseif arg.head == :tuple
        list = arg.args
    else
        error("Not recgonized arg")
    end
    decls = []
    for sym in list
        e = :($(esc(sym))(args...) = weval($(Expr(:quote, sym))(args...)))
        push!(decls, e)
    end
    Expr(:block, decls...)
end


text:
# Autogenerated wrapper script for FMUComplianceChecker_jll for x86_64-unknown-freebsd
export fmucheck

JLLWrappers.@generate_wrapper_header("FMUComplianceChecker")
JLLWrappers.@declare_executable_product(fmucheck)
function __init__()
    JLLWrappers.@generate_init_header()
    JLLWrappers.@init_executable_product(
        fmucheck,
        "bin/fmuCheck",
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
module Json

import Revise
import JSON, HTTP
using Genie, Genie.Renderer

const JSONParser = JSON
const JSON_FILE_EXT = ".json.jl"
const JSONString = String

export JSONString, json

function render(viewfile::Genie.Renderer.FilePath; context::Module = @__MODULE__, vars...) :: Function
  Genie.Renderer.registervars(vars...)
  Genie.Renderer.injectvars(context)

  () -> (Base.include(context, string(viewfile)) |> JSONParser.json)
end

function render(data::Any; forceparse::Bool = false) :: Function
  () -> JSONParser.json(data)
end

function Genie.Renderer.render(::Type{MIME"application/json"}, datafile::Genie.Renderer.FilePath; context::Module = @__MODULE__, vars...) :: Genie.Renderer.WebRenderable
  Genie.Renderer.WebRenderable(render(datafile; context = context, vars...), :json)
end

function Genie.Renderer.render(::Type{MIME"application/json"}, data::String; context::Module = @__MODULE__, vars...) :: Genie.Renderer.WebRenderable
  Genie.Renderer.WebRenderable(render(data; context = context, vars...), :json)
end

function Genie.Renderer.render(::Type{MIME"application/json"}, data::Any) :: Genie.Renderer.WebRenderable
  Genie.Renderer.WebRenderable(render(data), :json)
end

"""
"""
function json(resource::Genie.Renderer.ResourcePath, action::Genie.Renderer.ResourcePath; context::Module = @__MODULE__,
              status::Int = 200, headers::Genie.Renderer.HTTPHeaders = Genie.Renderer.HTTPHeaders(), vars...) :: Genie.Renderer.HTTP.Response
  json(Genie.Renderer.Path(joinpath(Genie.config.path_resources, string(resource), Renderer.VIEWS_FOLDER, string(action) * JSON_FILE_EXT));
        context = context, status = status, headers = headers, vars...)
end

"""
"""
function json(datafile::Genie.Renderer.FilePath; context::Module = @__MODULE__,
              status::Int = 200, headers::Genie.Renderer.HTTPHeaders = Genie.Renderer.HTTPHeaders(), vars...) :: Genie.Renderer.HTTP.Response
  Genie.Renderer.WebRenderable(Genie.Renderer.render(MIME"application/json", datafile; context = context, vars...), :json, status, headers) |> Genie.Renderer.respond
end

"""
"""
function json(data::String; context::Module = @__MODULE__,
              status::Int = 200, headers::Genie.Renderer.HTTPHeaders = Genie.Renderer.HTTPHeaders(), vars...) :: Genie.Renderer.HTTP.Response
  Genie.Renderer.WebRenderable(Genie.Renderer.render(MIME"application/json", data; context = context, vars...), :json, status, headers) |> Genie.Renderer.respond
end

"""
"""
function json(data; status::Int = 200, headers::Genie.Renderer.HTTPHeaders = Genie.Renderer.HTTPHeaders()) :: Genie.Renderer.HTTP.Response
  Genie.Renderer.WebRenderable(Genie.Renderer.render(MIME"application/json", data), :json, status, headers) |> Genie.Renderer.respond
end

### === ###
### EXCEPTIONS ###

function Genie.Router.error(error_message::String, ::Type{MIME"application/json"}, ::Val{500}; error_info::String = "") :: HTTP.Response
  json(Dict("error" => "500 Internal Error - $error_message", "info" => error_info), status = 500)
end

function Genie.Router.error(error_message::String, ::Type{MIME"application/json"}, ::Val{404}; error_info::String = "") :: HTTP.Response
  json(Dict("error" => "404 Not Found - $error_message", "info" => error_info), status = 404)
end

function Genie.Router.error(error_code::Int, error_message::String, ::Type{MIME"application/json"}; error_info::String = "") :: HTTP.Response
  json(Dict("error" => "$error_code Error - $error_message", "info" => error_info), status = error_code)
end

end


text:
using Flux, MNIST
using Flux: onehotbatch, argmax, mse, throttle
using Base.Iterators: repeated

x, y = traindata()
y = onehotbatch(y, 0:9)

m = Chain(
    Dense(28^2, 32, σ),
    Dense(32, 10),
    softmax
)

using CLArrays
using GPUArrays: JLArray
using CLArrays: GlobalArray, GlobalPointer, PreDeviceArray
using Flux: OneHotMatrix

cl(x) = x
cl(x::JLArray) = x
cl(xs::AbstractArray) = isbits(xs) ? xs : JLArray(xs)
cl(xs::Flux.TrackedArray) = Flux.TrackedArray(xs.f, cl(xs.data), Base.RefValue(cl(Flux.Tracker.grad(xs))))
cl(xs::Flux.OneHotMatrix) = Flux.OneHotMatrix(cl(xs.data))

CLArrays.kernel_convert(x::OneHotMatrix{T}) where T <: CLArray = OneHotMatrix(CLArrays.kernel_convert(x.data))
CLArrays.predevice_type(::Type{OneHotMatrix{T}}) where T <: GlobalArray = OneHotMatrix{CLArrays.predevice_type(T)}
CLArrays.device_type(x::OneHotMatrix{T}) where T <: CLArray = OneHotMatrix{CLArrays.device_type(x.data)}
CLArrays.reconstruct(x::OneHotMatrix{T}, ptr::GlobalPointer) where T <: PreDeviceArray = OneHotMatrix(CLArrays.reconstruct(x.data, ptr))
GPUArrays.arg_length(x::OneHotMatrix{T}) where T <: GPUArrays.GPUArray = UInt32.(size(x))
GPUArrays.to_device(state, x::OneHotMatrix{<: JLArray}) = OneHotMatrix(GPUArrays.to_device(state, x.data))
x, y = cl(x), cl(y)
m = mapparams(cl, m)
loss(x, y) = mse(m(x), y)

dataset = repeated((x, y), 500)
evalcb = () -> @show(loss(x, y))
opt = SGD(params(m), 1)

Flux.train!(loss, dataset, opt, cb = throttle(evalcb, 10))

# Check the prediction for the first digit
argmax(m(x[:,1]), 0:9) == argmax(y[:,1], 0:9)


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

# Compile
params = Params(nsteps=50)
simulate(params)

# 10k simulation
params = Params(
    nsteps=2000,
    x0 = getcoor("./ne10k_initial.pdb"),
    cutoff = 12.,
    box = Box([ 46.37, 46.37, 46.37 ], 12., lcell=2)
)
@time simulate(params)


text:
using InteractiveUtils

println(versioninfo())


text:
# ---
# title: 807. Max Increase to Keep City Skyline
# id: problem807
# author: Indigo
# date: 2021-06-23
# difficulty: Medium
# categories:
# link: <https://leetcode.com/problems/max-increase-to-keep-city-skyline/description/>
# hidden: true
# ---
#
# In a 2 dimensional array `grid`, each value `grid[i][j]` represents the height
# of a building located there. We are allowed to increase the height of any
# number of buildings, by any amount (the amounts can be different for different
# buildings). Height 0 is considered to be a building as well.
#
# At the end, the "skyline" when viewed from all four directions of the grid,
# i.e. top, bottom, left, and right, must be the same as the skyline of the
# original grid. A city's skyline is the outer contour of the rectangles formed
# by all the buildings when viewed from a distance. See the following example.
#
# What is the maximum total sum that the height of the buildings can be
# increased?
#
#
#
#     **Example:**
#     Input: grid = [[3,0,8,4],[2,4,5,7],[9,2,6,3],[0,3,1,0]]
#     Output: 35
#     Explanation:
#     The grid is:
#     [ [3, 0, 8, 4],
#       [2, 4, 5, 7],
#       [9, 2, 6, 3],
#       [0, 3, 1, 0] ]
#
#     The skyline viewed from top or bottom is: [9, 4, 8, 7]
#     The skyline viewed from left or right is: [8, 7, 9, 3]
#
#     The grid after increasing the height of buildings without affecting skylines is:
#
#     gridNew = [ [8, 4, 8, 7],
#                 [7, 4, 7, 7],
#                 [9, 4, 8, 7],
#                 [3, 3, 3, 3] ]
#
#
#
# **Notes:**
#
#   * `1 < grid.length = grid[0].length <= 50`.
#   * All heights `grid[i][j]` are in the range `[0, 100]`.
#   * All buildings in `grid[i][j]` occupy the entire grid cell: that is, they are a `1 x 1 x grid[i][j]` rectangular prism.
#
#
## @lc code=start
using LeetCode

function max_increase_keeping_skyline(grid::Matrix{Int})
    n = size(grid, 1)
    col_max = maximum(grid; dims=1)
    row_max = maximum(grid; dims=2)
    res = 0
    for i in 1:n, j in 1:n
        res += min(row_max[i], col_max[j]) - grid[i, j]
    end
    return res
end
## @lc code=end


text:
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/JuliaFEM.jl/blob/master/LICENSE.md

using JuliaFEM
using JuliaFEM.Testing

@testset "dict field" begin
    el = Element(Seg2, 1, [1, 2])
    X = Dict{Int64, Vector{Float64}}(1 => [0.0, 0.0], 2 => [1.0, 0.0], 3 => [0.5, 0.5])
    f = Field(X)
    debug("field = $f")
    #update!(el, "geometry", X)
    el["geometry"] = f
    @test isapprox(el("geometry")[1], [0.0, 0.0])
    @test isapprox(el("geometry", 0.0)[1], [0.0, 0.0])
    @test isapprox(el("geometry", 0.0)[3], [0.5, 0.5])
    @test isapprox(el("geometry", [0.0], 0.0), [0.5, 0.0])
end


text:
# These can be changed, to trade off better performance for space
const global maxallowedprobe = isdefined(Base, :maxallowedprobe) ? Base.maxallowedprobe : 16
const global maxprobeshift   = isdefined(Base, :maxprobeshift) ? Base.maxprobeshift : 6

# OrderedDict

"""
    OrderedDict

`OrderedDict`s are  simply dictionaries  whose entries  have a  particular order.  The order
refers to insertion order, which allows deterministic iteration over the dictionary or set.
"""
mutable struct OrderedDict{K,V} <: AbstractDict{K,V}
    slots::Array{Int32,1}
    keys::Array{K,1}
    vals::Array{V,1}
    ndel::Int
    maxprobe::Int
    dirty::Bool

    function OrderedDict{K,V}() where {K,V}
        new{K,V}(zeros(Int32,16), Vector{K}(), Vector{V}(), 0, 0, false)
    end
    function OrderedDict{K,V}(kv) where {K,V}
        h = OrderedDict{K,V}()
        for (k,v) in kv
            h[k] = v
        end
        return h
    end
    OrderedDict{K,V}(p::Pair) where {K,V} = setindex!(OrderedDict{K,V}(), p.second, p.first)
    function OrderedDict{K,V}(ps::Pair...) where {K,V}
        h = OrderedDict{K,V}()
        sizehint!(h, length(ps))
        for p in ps
            h[p.first] = p.second
        end
        return h
    end
    function OrderedDict{K,V}(d::OrderedDict{K,V}) where {K,V}
        if d.ndel > 0
            rehash!(d)
        end
        @assert d.ndel == 0
        new{K,V}(copy(d.slots), copy(d.keys), copy(d.vals), 0, d.maxprobe, false)
    end
end
OrderedDict() = OrderedDict{Any,Any}()
OrderedDict(kv::Tuple{}) = OrderedDict()
copy(d::OrderedDict) = OrderedDict(d)

# TODO: this can probably be simplified using `eltype` as a THT (Tim Holy trait)
# OrderedDict{K,V}(kv::Tuple{Vararg{Tuple{K,V}}})     = OrderedDict{K,V}(kv)
# OrderedDict{K  }(kv::Tuple{Vararg{Tuple{K,Any}}})   = OrderedDict{K,Any}(kv)
# OrderedDict{V  }(kv::Tuple{Vararg{Tuple{Any,V}}})   = OrderedDict{Any,V}(kv)
OrderedDict(kv::Tuple{Vararg{Pair{K,V}}}) where {K,V}  = OrderedDict{K,V}(kv)

OrderedDict(kv::AbstractArray{Tuple{K,V}}) where {K,V} = OrderedDict{K,V}(kv)
OrderedDict(kv::AbstractArray{Pair{K,V}}) where {K,V}  = OrderedDict{K,V}(kv)
OrderedDict(kv::AbstractDict{K,V}) where {K,V}         = OrderedDict{K,V}(kv)

OrderedDict(ps::Pair{K,V}...) where {K,V} = OrderedDict{K,V}(ps)
OrderedDict(ps::Pair...)                  = OrderedDict(ps)

function OrderedDict(kv)
    try
        dict_with_eltype((K, V) -> OrderedDict{K, V}, kv, eltype(kv))
    catch e
        if isempty(methods(iterate, (typeof(kv),))) ||
            !all(x->isa(x, Union{Tuple,Pair}), kv)
            throw(ArgumentError("OrderedDict(kv): kv needs to be an iterator of tuples or pairs"))
        else
            rethrow(e)
        end
    end
end

empty(d::OrderedDict{K,V}) where {K,V} = OrderedDict{K,V}()
empty(d::OrderedDict, ::Type{K}, ::Type{V}) where {K, V} = OrderedDict{K, V}()

length(d::OrderedDict) = length(d.keys) - d.ndel
isempty(d::OrderedDict) = (length(d) == 0)

"""
    isordered(::Type)

Property of associative containers, that is `true` if the container type has a
defined order (such as `OrderedDict` and `SortedDict`), and `false` otherwise.
"""
isordered(::Type{T}) where {T<:AbstractDict} = false
isordered(::Type{T}) where {T<:OrderedDict} = true

# conversion between OrderedDict types
function convert(::Type{OrderedDict{K,V}}, d::AbstractDict) where {K,V}
    if !isordered(typeof(d))
        Base.depwarn("Conversion to OrderedDict is deprecated for unordered associative containers (in this case, $(typeof(d))). Use an ordered or sorted associative type, such as SortedDict and OrderedDict.", :convert)
    end
    h = OrderedDict{K,V}()
    for (k,v) in d
        ck = convert(K,k)
        if !haskey(h,ck)
            h[ck] = convert(V,v)
        else
            error("key collision during dictionary conversion")
        end
    end
    return h
end
convert(::Type{OrderedDict{K,V}},d::OrderedDict{K,V}) where {K,V} = d

isslotempty(slot_value::Integer) = slot_value == 0
isslotfilled(slot_value::Integer) = slot_value > 0
isslotmissing(slot_value::Integer) = slot_value < 0

function rehash!(h::OrderedDict{K,V}, newsz = length(h.slots)) where {K,V}
    olds = h.slots
    keys = h.keys
    vals = h.vals
    sz = length(olds)
    newsz = _tablesz(newsz)
    h.dirty = true
    count0 = length(h)
    if count0 == 0
        resize!(h.slots, newsz)
        fill!(h.slots, 0)
        resize!(h.keys, 0)
        resize!(h.vals, 0)
        h.ndel = 0
        return h
    end

    slots = zeros(Int32, newsz)
    maxprobe = 0

    if h.ndel > 0
        ndel0 = h.ndel
        ptrs = !isbitstype(K)
        to = 1
        # TODO: to get the best performance we need to avoid reallocating these.
        # This algorithm actually works in place, unless the dict is modified
        # due to GC during this process.
        newkeys = similar(keys, count0)
        newvals = similar(vals, count0)
        @inbounds for from = 1:length(keys)
            if !ptrs || isassigned(keys, from)
                k = keys[from]
                hashk = hash(k)%Int
                isdeleted = false
                if !ptrs
                    iter = 0
                    index = (hashk & (sz-1)) + 1
                    while iter <= h.maxprobe
                        si = olds[index]
                        si == from && break
                        # if we find si == 0, then the key was deleted and it's slot was reused/overwritten
                        (si == -from || si == 0) && (isdeleted = true; break)
                        index = (index & (sz-1)) + 1
                        iter += 1
                    end
                    iter > h.maxprobe && (isdeleted = true)  # Another case where the slot was reused/overwritten
                end
                if !isdeleted
                    index0 = index = (hashk & (newsz-1)) + 1
                    while slots[index] != 0
                        index = (index & (newsz-1)) + 1
                    end
                    probe = (index - index0) & (newsz-1)
                    probe > maxprobe && (maxprobe = probe)
                    slots[index] = to
                    newkeys[to] = k
                    newvals[to] = vals[from]
                    to += 1
                end
                if h.ndel != ndel0
                    # if items are removed by finalizers, retry
                    return rehash!(h, newsz)
                end
            end
        end
        h.keys = newkeys
        h.vals = newvals
        h.ndel = 0
    else
        @inbounds for i = 1:count0
            k = keys[i]
            index0 = index = hashindex(k, newsz)
            while slots[index] != 0
                index = (index & (newsz-1)) + 1
            end
            probe = (index - index0) & (newsz-1)
            probe > maxprobe && (maxprobe = probe)
            slots[index] = i
            if h.ndel > 0
                # if items are removed by finalizers, retry
                return rehash!(h, newsz)
            end
        end
    end

    h.slots = slots
    h.maxprobe = maxprobe
    return h
end

function sizehint!(d::OrderedDict, newsz)
    slotsz = (newsz*3)>>1
    oldsz = length(d.slots)
    if slotsz <= oldsz
        # todo: shrink
        # be careful: rehash!() assumes everything fits. it was only designed
        # for growing.
        return d
    end
    # grow at least 25%
    slotsz = max(slotsz, (oldsz*5)>>2)
    rehash!(d, slotsz)
end

function empty!(h::OrderedDict{K,V}) where {K,V}
    fill!(h.slots, 0)
    empty!(h.keys)
    empty!(h.vals)
    h.ndel = 0
    h.dirty = true
    return h
end

# get the index where a key is stored, or -1 if not present
function ht_keyindex(h::OrderedDict{K,V}, key, direct) where {K,V}
    slots = h.slots
    sz = length(slots)
    iter = 0
    maxprobe = h.maxprobe
    index = hashindex(key, sz)
    keys = h.keys

    @inbounds while iter <= maxprobe
        si = slots[index]
        isslotempty(si) && break
        if isslotfilled(si) && isequal(key, keys[si])
            return ifelse(direct, oftype(index, si), index)
        end

        index = (index & (sz-1)) + 1
        iter += 1
    end

    return -1
end

# get the index where a key is stored, or -pos if not present
# and the key would be inserted at pos
# This version is for use by setindex! and get!
function ht_keyindex2(h::OrderedDict{K,V}, key) where {K,V}
    slots = h.slots
    sz = length(slots)
    iter = 0
    maxprobe = h.maxprobe
    index = hashindex(key, sz)
    keys = h.keys
    avail = 0

    @inbounds while iter <= maxprobe
        si = slots[index]
        if isslotempty(si)
            avail < 0 && return avail
            return -index
        end

        if isslotmissing(si)
            avail == 0 && (avail = -index)
        elseif isequal(key, keys[si])
            return oftype(index, si)
        end

        index = (index & (sz-1)) + 1
        iter += 1
    end

    avail < 0 && return avail

    # If key is not present, may need to keep searching to find slot
    maxallowed = max(maxallowedprobe, sz>>maxprobeshift)
    @inbounds while iter < maxallowed
        if !isslotfilled(slots[index])
            h.maxprobe = iter
            return -index
        end
        index = (index & (sz-1)) + 1
        iter += 1
    end

    rehash!(h, length(h) > 64000 ? sz*2 : sz*4)

    return ht_keyindex2(h, key)
end

function _setindex!(h::OrderedDict, v, key, index)
    hk, hv = h.keys, h.vals
    #push!(h.keys, key)
    ccall(:jl_array_grow_end, Cvoid, (Any, UInt), hk, 1)
    nk = length(hk)
    @inbounds hk[nk] = key
    #push!(h.vals, v)
    ccall(:jl_array_grow_end, Cvoid, (Any, UInt), hv, 1)
    @inbounds hv[nk] = v
    @inbounds h.slots[index] = nk
    h.dirty = true

    sz = length(h.slots)
    cnt = nk - h.ndel
    # Rehash now if necessary
    if h.ndel >= ((3*nk)>>2) || cnt*3 > sz*2
        # > 3/4 deleted or > 2/3 full
        rehash!(h, cnt > 64000 ? cnt*2 : cnt*4)
    end
end

function setindex!(h::OrderedDict{K,V}, v0, key0) where {K,V}
    key = convert(K, key0)
    if !isequal(key, key0)
        throw(ArgumentError("$key0 is not a valid key for type $K"))
    end
    v = convert(V, v0)

    index = ht_keyindex2(h, key)

    if index > 0
        @inbounds h.keys[index] = key
        @inbounds h.vals[index] = v
    else
        _setindex!(h, v, key, -index)
    end

    return h
end

function get!(h::OrderedDict{K,V}, key0, default) where {K,V}
    key = convert(K, key0)
    if !isequal(key, key0)
        throw(ArgumentError("$key0 is not a valid key for type $K"))
    end

    index = ht_keyindex2(h, key)

    index > 0 && return h.vals[index]

    v = convert(V,  default)
    _setindex!(h, v, key, -index)
    return v
end

function get!(default::Base.Callable, h::OrderedDict{K,V}, key0) where {K,V}
    key = convert(K, key0)
    if !isequal(key, key0)
        throw(ArgumentError("$key0 is not a valid key for type $K"))
    end

    index = ht_keyindex2(h, key)

    index > 0 && return h.vals[index]

    h.dirty = false
    v = convert(V,  default())
    if h.dirty  # calling default could have dirtied h
        index = ht_keyindex2(h, key)
    end
    if index > 0
        h.keys[index] = key
        h.vals[index] = v
    else
        _setindex!(h, v, key, -index)
    end
    return v
end

function getindex(h::OrderedDict{K,V}, key) where {K,V}
    index = ht_keyindex(h, key, true)
    return (index<0) ? throw(KeyError(key)) : h.vals[index]::V
end

function get(h::OrderedDict{K,V}, key, default) where {K,V}
    index = ht_keyindex(h, key, true)
    return (index<0) ? default : h.vals[index]::V
end

function get(default::Base.Callable, h::OrderedDict{K,V}, key) where {K,V}
    index = ht_keyindex(h, key, true)
    return (index<0) ? default() : h.vals[index]::V
end

haskey(h::OrderedDict, key) = (ht_keyindex(h, key, true) >= 0)
in(key, v::Base.KeySet{K,T}) where {K,T<:OrderedDict{K}} = (ht_keyindex(v.dict, key, true) >= 0)

function getkey(h::OrderedDict{K,V}, key, default) where {K,V}
    index = ht_keyindex(h, key, true)
    return (index<0) ? default : h.keys[index]::K
end

function _pop!(h::OrderedDict, index)
    @inbounds val = h.vals[h.slots[index]]
    _delete!(h, index)
    return val
end

function pop!(h::OrderedDict)
    h.ndel > 0 && rehash!(h)
    key = h.keys[end]
    index = ht_keyindex(h, key, false)
    return key => _pop!(h, index)
end

function popfirst!(h::OrderedDict)
    h.ndel > 0 && rehash!(h)
    key = h.keys[1]
    index = ht_keyindex(h, key, false)
    key => _pop!(h, index)
end

function pop!(h::OrderedDict, key)
    index = ht_keyindex(h, key, false)
    index > 0 ? _pop!(h, index) : throw(KeyError(key))
end

function pop!(h::OrderedDict, key, default)
    index = ht_keyindex(h, key, false)
    index > 0 ? _pop!(h, index) : default
end

function _delete!(h::OrderedDict, index)
    @inbounds ki = h.slots[index]
    @inbounds h.slots[index] = -ki
    ccall(:jl_arrayunset, Cvoid, (Any, UInt), h.keys, ki-1)
    ccall(:jl_arrayunset, Cvoid, (Any, UInt), h.vals, ki-1)
    h.ndel += 1
    h.dirty = true
    return h
end

function delete!(h::OrderedDict, key)
    index = ht_keyindex(h, key, false)
    if index > 0; _delete!(h, index); end
    return h
end

function iterate(t::OrderedDict)
    t.ndel > 0 && rehash!(t)
    length(t.keys) < 1 && return nothing
    return (Pair(t.keys[1], t.vals[1]), 2)
end
function iterate(t::OrderedDict, i)
    length(t.keys) < i && return nothing
    return (Pair(t.keys[i], t.vals[i]), i+1)
end

function _merge_kvtypes(d, others...)
    K, V = keytype(d), valtype(d)
    for other in others
        K = promote_type(K, keytype(other))
        V = promote_type(V, valtype(other))
    end
    return (K,V)
end

function merge(d::OrderedDict, others::AbstractDict...)
    K,V = _merge_kvtypes(d, others...)
    merge!(OrderedDict{K,V}(), d, others...)
end

function merge(combine::Function, d::OrderedDict, others::AbstractDict...)
    K,V = _merge_kvtypes(d, others...)
    merge!(combine, OrderedDict{K,V}(), d, others...)
end

function Base.map!(f, iter::Base.ValueIterator{<:OrderedDict})
    dict = iter.dict
    vals = dict.vals
    elements = length(vals) - dict.ndel
    elements == 0 && return iter
    for i in dict.slots
        if i > 0
            @inbounds vals[i] = f(vals[i])
            elements -= 1
            elements == 0 && break
        end
    end
    return iter
end


text:
using MoodleQuestions
using Test

@testset "ReadFromSWAD" begin
    quiz = read_swad("../input_data/test_swad.xml")
    @test quiz != nothing
    @test length(quiz.multiples)==419
    @test quiz.multiples[1].shuffle == false
    @test quiz.multiples[3].shuffle == true
    @test length(quiz.categories) > 0
end

@testset "ReadRightFromTXT" begin
    content = """
    * Category 1

    Question 1

    - Option 1.1.
    - Option 1.2.
    + Option 1.3.

    * Category 2

    Question 2

    + Option 2.1.
    - Option 2.2.
    """
    file = IOBuffer(content)
    quiz = read_txt(file)
    @test length(quiz.categories)==2
    @test quiz.categories[1]=="Category 1"
    @test quiz.categories[2]=="Category 2"
    @test !isempty(quiz.multiples)
    @test length(quiz.multiples)==2
    @test quiz.multiples[1].question == "Question 1"
    @test quiz.multiples[2].question == "Question 2"
    @test quiz.multiples[1].rights == [3]
    @test quiz.multiples[2].rights == [1]
end

@testset "ReadWithout category" begin
    content = """
    Question 1.
    - Option 1.
    + Option 2.
"""
    quiz = read_txt(IOBuffer(content))
    @test length(quiz.categories) == 1
    @test quiz.categories[1] == "Default"
end

@testset "Reading multiple" begin
    content = """
    Question 1.
    - Option 1.
    + Option 2.
    - Option 3.
    + Option 4.
"""
    quiz = read_txt(IOBuffer(content))
    question = only(quiz.multiples)
    @test length(question.options)==4
    @test question.rights == [2,4]
end

@testset "Reading multiple" begin
    content = """
Pregunta Buena.
- Opción 1.
+ Opción 2.

Pregunta 2
+ Opción 2.1.
- Opción 2.2.
+ Opción 2.3.
"""
    quiz = read_txt(IOBuffer(content))
    question = quiz.multiples[1]
    @test length(question.options)==2
    @test question.rights == [2]
    question = quiz.multiples[2]
    @test length(question.options)==3
    @test question.rights == [1,3]
end

@testset "Reading essays" begin
    content = """
Pregunta Buena.
- Opción 1.
+ Opción 2.

[Pregunta 2]

Pregunta Buena.
+ Opción 1.
"""
    quiz = read_txt(IOBuffer(content))
    @test length(quiz.multiples) == 2
    question = quiz.multiples[1]
    @test length(question.options)==2
    @test question.rights == [2]
    question = only(quiz.essays)
    @test question.question =="Pregunta 2"
end

@testset "Reading text" begin
    content = """
Pregunta Buena.
- Opción 1.
+ Opción 2.

[Pregunta 2]

Pregunta 3 [correcta]

Pregunta Buena.
+ Opción 1.
"""
    quiz = read_txt(IOBuffer(content))
    @test length(quiz.multiples) == 2
    question = quiz.multiples[1]
    @test length(question.options)==2
    @test question.rights == [2]
    @test length(quiz.texts) == 1
    question = only(quiz.texts)
    @test question.answer == "correcta"
    @test question.question == "Pregunta 3"
    question = only(quiz.essays)
    @test question.question =="Pregunta 2"
end

@testset "Error in server" begin
    content = """hola. +"""
    quiz = read_txt(IOBuffer(content))
    @test length(quiz.booleans) == 1
end

max_stars_repo_name: dmolina/MoodleQuestions

max_issues_repo_name: dmolina/MoodleQuestions

max_forks_repo_name: dmolina/MoodleQuestions


text:
### A Pluto.jl notebook ###
# v0.11.14

using Markdown
using InteractiveUtils

# ╔═╡ 7085c940-f389-11ea-1dec-59018061e9b5
using HTTP

# ╔═╡ fb93f836-f389-11ea-26e6-678b961ba787
using LinearAlgebra, GLM, Optim, ForwardDiff

# ╔═╡ fbcefcc6-f389-11ea-2258-6fa3ead65683
using Random, Statistics, FreqTables

# ╔═╡ fbd5e410-f389-11ea-03f8-b90572b6e609
using DataFrames, CSV

# ╔═╡ 57fae8cc-f38b-11ea-3321-21e2b433ebc3
begin
	url = "https://raw.githubusercontent.com/OU-PhD-Econometrics/fall-2020/master/ProblemSets/PS3-gev/nlsw88w.csv"
	df = CSV.read(HTTP.get(url).body)
	X = [df.age df.white df.collgrad]
	Z = hcat(df.elnwage1, df.elnwage2, df.elnwage3, df.elnwage4,
	df.elnwage5, df.elnwage6, df.elnwage7, df.elnwage8)
	y = df.occupation;

end

# ╔═╡ 59dc3cb8-f390-11ea-02c0-1f33de75a368
function mlogit(β, γ, X, Z, y)
	K = size(X,2) # nvars
    J = length(unique(y)) # n options
    N = length(y) # N
    bigY = zeros(N,J)
    bigY[:,J] = y.==J # di
	params = [β.*ones(K,J-1) zeros(K,1) γ.*ones(K,1)] # Setting βJ to zero
    #params = [reshape(β,K,J-1) zeros(K,1) reshape(γ,K,1)] # Setting βJ to zero
	T = promote_type(eltype(X),eltype(β)) # this line is new. I is relevant for solution algorithm
    num   = zeros(T,N,J)                      # this line is new
    dem   = zeros(T,N)                        # this line is new

	for j=1:J
		Xs = (X*params[:,j])
		Zs = (Z[:,j] - Z[:,J])*params[end,end][1]
		num[:,j] = exp.(Xs + Zs)
        dem .+= num[:,j] # Does not change
     end

     P = num./repeat(dem,1,J)

     loglike = -sum( bigY.*log.(P) ) # Negative to maximize (minimize negative)

     return loglike
end

# ╔═╡ dcd7003e-f3ac-11ea-0a64-79dd7a7ce64d
begin
	nvars = size(X,2);
	func = TwiceDifferentiable(
		vars -> mlogit(
			vars[1:nvars],
			vars[end]', X, Z, y),
		zeros(nvars+1);  # or ones
		autodiff=:forward)
end

# ╔═╡ 916db0da-f395-11ea-3b20-85a3a8f4dc4e
opt = optimize(func, ones(nvars+1),
	LBFGS(),
	Optim.Options(g_tol = 1e-5, iterations=100_000, show_trace=true, show_every=50)
)

# ╔═╡ 5d21c9b2-f3bd-11ea-07b2-3537c0bbab7b
# evaluate the Hessian at the estimates
H  = Optim.hessian!(func, opt.minimizer)

# ╔═╡ 5d23281e-f3bd-11ea-2910-d7d85c6dc661
σ = sqrt.(diag(inv(H))) # standard errors = sqrt(diag(inv(H))) [usually it's -H but we've already multiplied the obj fun by -1]

# ╔═╡ aebc9c80-f392-11ea-39f2-2d6856bb2beb
opt.minimizer[end]

# ╔═╡ e30c1074-f3c1-11ea-1423-ed75c21954f5

# ╔═╡ de67438e-f3c1-11ea-39be-b5411a7aaf13

# ╔═╡ c28c774e-f3c1-11ea-169f-3da012e05660

# ╔═╡ a7d8eb24-f3c1-11ea-1fbd-5b725349f0c3

# ╔═╡ a20731ba-f3c1-11ea-0348-61490921bafe

# ╔═╡ 9f6ebe64-f3c1-11ea-290e-918cfe19f6d5

# ╔═╡ 98fc362e-f38f-11ea-17ae-d3f68d90ce79

# ╔═╡ 8a224998-f38f-11ea-21b4-4b8a5b38f0ae

# ╔═╡ 6977c62a-f38f-11ea-3813-e76984698d90

# ╔═╡ Cell order:
# ╠═7085c940-f389-11ea-1dec-59018061e9b5
# ╠═fb93f836-f389-11ea-26e6-678b961ba787
# ╠═fbcefcc6-f389-11ea-2258-6fa3ead65683
# ╠═fbd5e410-f389-11ea-03f8-b90572b6e609
# ╠═57fae8cc-f38b-11ea-3321-21e2b433ebc3
# ╠═59dc3cb8-f390-11ea-02c0-1f33de75a368
# ╠═dcd7003e-f3ac-11ea-0a64-79dd7a7ce64d
# ╠═916db0da-f395-11ea-3b20-85a3a8f4dc4e
# ╠═5d21c9b2-f3bd-11ea-07b2-3537c0bbab7b
# ╠═5d23281e-f3bd-11ea-2910-d7d85c6dc661
# ╠═aebc9c80-f392-11ea-39f2-2d6856bb2beb
# ╠═e30c1074-f3c1-11ea-1423-ed75c21954f5
# ╠═de67438e-f3c1-11ea-39be-b5411a7aaf13
# ╠═c28c774e-f3c1-11ea-169f-3da012e05660
# ╠═a7d8eb24-f3c1-11ea-1fbd-5b725349f0c3
# ╠═a20731ba-f3c1-11ea-0348-61490921bafe
# ╠═9f6ebe64-f3c1-11ea-290e-918cfe19f6d5
# ╠═98fc362e-f38f-11ea-17ae-d3f68d90ce79
# ╠═8a224998-f38f-11ea-21b4-4b8a5b38f0ae
# ╠═6977c62a-f38f-11ea-3813-e76984698d90


text:
# Replay buffer that store full episodes

mutable struct EpisodeReplayBuffer
    max_size::Int64
    batch_size::Int64
    trace_length::Int64
    rng::AbstractRNG
    _curr_size::Int64
    _idx::Int64
    _experience::Vector{Vector{DQExperience}}

    _s_batch::Array{Float64}
    _a_batch::Array{Int64}
    _r_batch::Array{Float64}
    _sp_batch::Array{Float64}
    _done_batch::Array{Bool}
    _trace_mask::Array{Int64}

    function EpisodeReplayBuffer(env::AbstractEnvironment,
                          max_size::Int64,
                          batch_size::Int64,
                          trace_length::Int64,
                          rng::AbstractRNG = MersenneTwister(0))
        s_dim = obs_dimensions(env)
        experience = Vector{Vector{DQExperience}}(max_size)
        _s_batch = zeros(batch_size, trace_length, s_dim...)
        _a_batch = zeros(Int64, batch_size, trace_length)
        _r_batch = zeros(batch_size, trace_length)
        _sp_batch = zeros(batch_size, trace_length, s_dim...)
        _done_batch = zeros(Bool, batch_size, trace_length)
        _trace_mask = zeros(Int64, batch_size, trace_length)
        return new(max_size, batch_size, trace_length, rng, 0, 1, experience,
                   _s_batch, _a_batch, _r_batch, _sp_batch, _done_batch, _trace_mask)
    end
end

is_full(r::EpisodeReplayBuffer) = r._curr_size == r.max_size

max_size(r::EpisodeReplayBuffer) = r.max_size

function add_episode!(r::EpisodeReplayBuffer, ep::Vector{DQExperience})
    r._experience[r._idx] = ep
    r._idx = mod1((r._idx + 1),r.max_size)
    if r._curr_size < r.max_size
        r._curr_size += 1
    end
end

function reset_batches!(r::EpisodeReplayBuffer)
    fill!(r._s_batch, 0.)
    fill!(r._a_batch, 0)
    fill!(r._r_batch, 0.)
    fill!(r._sp_batch, 0.)
    fill!(r._done_batch, false)
    fill!(r._trace_mask, 0)
end

function StatsBase.sample(r::EpisodeReplayBuffer)
    reset_batches!(r) # might not be necessary
    @assert r._curr_size >= r.batch_size
    @assert r.max_size >= r.batch_size # could be checked during construction
    sample_indices = sample(r.rng, 1:r._curr_size, r.batch_size, replace=false)
    @assert length(sample_indices) == size(r._s_batch)[1]
    for (i, idx) in enumerate(sample_indices)
        ep = r._experience[idx]
        # randomized start TODO add as an option of the buffer
        ep_start = rand(r.rng, 1:length(ep))
        #ep_start = 1
        t = 1
        for j=ep_start:min(length(ep), r.trace_length)
            expe = ep[j]
            r._s_batch[i,t,indices(r._s_batch)[3:end]...] = expe.s
            r._a_batch[i,t] = expe.a
            r._r_batch[i,t] = expe.r
            r._sp_batch[i,t,indices(r._sp_batch)[3:end]...] = expe.sp
            r._done_batch[i,t] = expe.done
            r._trace_mask[i,t] = 1
            t += 1
        end
    end
    return r._s_batch, r._a_batch, r._r_batch, r._sp_batch, r._done_batch, r._trace_mask
end

function populate_replay_buffer!(r::EpisodeReplayBuffer,
                                 env::AbstractEnvironment;
                                 max_pop::Int64 = r.max_size,
                                 max_steps::Int64 = 2000)
    for t=1:(max_pop - r._curr_size)
        ep = generate_episode(env, max_steps=max_steps)
        add_episode!(r, ep)
    end
    @assert r._curr_size >= r.batch_size
end

function generate_episode(env::AbstractEnvironment; max_steps::Int64 = 2000)
    episode = DQExperience[]
    sizehint!(episode, max_steps)
    # start simulation
    o = reset(env)
    done = false
    step = 1
    while !done && step < max_steps
        # action = sample_action(env)
        action = get_fused_acasx_action(env)
        ai = action_index(env.problem, action)
        op, rew, done, info = step!(env, action)
        exp = DQExperience(o, ai, rew, op, done)
        push!(episode, exp)
        o = op
        step += 1
    end
    println("Done populating episode replay!")
    return episode
end

max_stars_repo_name: parachutel/DeepCorrectionCAS


text:
"""
$(TYPEDEF)

Abstract unordered collection of nodes in `D`-dimensional space. Type `T` is used to represent coordinates.
"""
abstract type AbstractCell{D, T} <: AbstractNodeCollection{D, T} end

###
### HomogeneousCell type

"""
$(TYPEDEF)
$(TYPEDFIELDS)

Unodered homogeneous collection of nodes in `D`-dimensional space.
"""
struct HomogeneousCell{D, T, L<:Union{Symbol,Nothing}} <: AbstractCell{D, T}
    """
    Coordinates of nodes.
    """
    cell_vectors::Vector{SVector{D,T}}
    """
    Label of the cell.
    """
    label::L
end

### HomogeneousCell constructors

@inline HomogeneousCell(cell_vectors) = HomogeneousCell(cell_vectors, nothing)
function HomogeneousCell(cell_vectors::Vector, label::Union{Symbol,Nothing}=nothing)
    D = first(cell_vectors) |> length
    for i = 2:length(cell_vectors)
        @assert length(cell_vectors[i])==D "All coordinates should have identical dimension."
    end
	T = promote_type(compute_type.(cell_vectors)...)
    return HomogeneousCell(map(SVector{D,T}, cell_vectors), label)
end

###
### InhomogeneousCell type

"""
$(TYPEDEF)
$(TYPEDFIELDS)

Unordered inhomogeneous collection of nodes in `D`-dimensional space. This type allows one to partition the nodes of the cell into several groups. Different groups of nodes may correspond to the different classes of physical objects occupying these nodes.
"""
struct InhomogeneousCell{D, T, N, L<:Union{Symbol,Nothing}, T′} <: AbstractCell{D, T}
    """
    Coordinates of nodes.
    """
    cell_vectors::ArrayPartition{T′, NTuple{N, Vector{SVector{D, T}}}}
    """
    Sizes of the homogeneous groups inside inhomogeneous cell.
    """
    group_sizes::NTuple{N, Int}
    """
    Label of the cell.
    """
    label::L
    InhomogeneousCell(cell_vectors::ArrayPartition{T′, NTuple{N, Vector{SVector{D, T}}}}, label::L) where {T′,T,N,D, L<:Union{Symbol,Nothing}} = new{D,T,N,L,T′}(cell_vectors, Tuple(length.(cell_vectors.x)), label)
end

### InhomogeneousCell constructors

@inline InhomogeneousCell(cell_vectors; label = nothing) = InhomogeneousCell(cell_vectors, label)
function InhomogeneousCell(cell_vectors::ArrayPartition{T′, NTuple{N, Vector{NTuple{D,T}}}}; label::Union{Symbol,Nothing} = nothing) where {T′,T,N,D}
    new_cell_vectors = similar(cell_vectors, SVector{D,T})
    new_cell_vectors .= cell_vectors
    return InhomogeneousCell(cell_vectors, label)
end
function InhomogeneousCell(vecss::Tuple{Vector, Vector, Vararg{Vector}}, label::Union{Symbol,Nothing})
    T = promote_type(map(x -> promote_type(compute_type.(x)...), vecss)...)
    D = length(vecss |> first |> first)
    cell_vectors = ArrayPartition(map(x -> SVector{D,T}.(x), vecss))
    return InhomogeneousCell(cell_vectors, label)
end
@inline InhomogeneousCell(cell_vectors1::Vector, cell_vectors2::Vector, vecss...; label::Union{Symbol,Nothing} = nothing) = InhomogeneousCell((cell_vectors1, cell_vectors2, vecss...), label)

compute_type(x::T) where {T<:Number} = T
compute_type(x::Tuple) = promote_type(typeof.(x)...)
compute_type(x::AbstractVector) = eltype(x)

###
### TrivialCell type

"""
$(TYPEDEF)

Trivial cell consisting of one node at the origin of `D`-dimensional coordinate system. The type `T` is used to represent coordinates.
"""
struct TrivialCell{D, T} <: AbstractCell{D, T} end

###
### length for AbstractCell

"""
`length(cell::AbstractCell)`

Returns the number of the nodes in the cell.
"""
@inline Base.length(cell::AbstractCell) = length(cell.cell_vectors)
@inline Base.length(cell::TrivialCell) = 1

###
### Helper functions to work with cell groups

"""
$(TYPEDSIGNATURES)

Return the number of separate groups in a cell.
"""
@inline num_of_groups(cell::Union{TrivialCell, HomogeneousCell}) = 1
@inline num_of_groups(cell::InhomogeneousCell{D,T,N}) where {D,T,N} = N

"""
$(TYPEDSIGNATURES)

Returns the size of the `ig`-th homogeneous group inside a cell.
"""
Base.@propagate_inbounds group_size(cell::Union{TrivialCell, HomogeneousCell}, ig::Int) = (@boundscheck ig==1 || throw(ErrorException("Group index is out of range.")); length(cell))
Base.@propagate_inbounds group_size(cell::InhomogeneousCell, ig::Int) = (@boundscheck 1<=ig<=num_of_groups(cell) || throw(ErrorException("Group index is out of range."));cell.group_sizes[ig])

###
### Indexing

"""
`getindex(cell::AbstractCell, i...)`

Returns the coordinate of the ``i``-th node of the cell. In the case of InhomogeneousCell we can use double index `i = i1, i2` to access ``i_1``-th node of ``i_2``-th group.
"""
Base.@propagate_inbounds function Base.getindex(cell::Union{HomogeneousCell, InhomogeneousCell}, ic::Int)
	@boundscheck check_cell_index(cell, ic)
	@inbounds getindex(cell.cell_vectors, ic)
end
Base.@propagate_inbounds function Base.getindex(cell::InhomogeneousCell, ic::Int, ig::Int)
	@boundscheck check_cell_index(cell, ic, ig)
	@inbounds getindex(cell.cell_vectors, ig, ic)
end
Base.@propagate_inbounds Base.getindex(cell::TrivialCell{D,T}, i::Int) where {D,T} = (@boundscheck check_cell_index(cell, i); zero(SVector{D,T}))

@inline check_cell_index(cell::TrivialCell, i::Int) = i==1 || throw(BoundsError(cell, i))
@inline check_cell_index(cell::Union{HomogeneousCell,InhomogeneousCell}, ic::Int) = (1<=ic<=length(cell)) || throw(BoundsError(cell, ic))
@inline check_cell_index(cell::InhomogeneousCell, ic::Int, ig::Int) =
    (1<=ig<=num_of_groups(cell)) && (1<=ic<=group_size(cell, ig)) || throw(BoundsError(cell, (ic, ig)))

###
### Conversion utilities

"""
`switch_coord_type(cell::AbstractCell{D, T}, ::Type{T′})`

Converts the type used to represent coordinates from `T` to `T′`.
"""
switch_coord_type(cell::TrivialCell{D,T}, ::Type{T′}) where {D,T,T′} = TrivialCell{D,T′}()
@inline switch_coord_type(cell::TrivialCell{D,T}, ::Type{T}) where {D,T} = cell
switch_coord_type(cell::HomogeneousCell{D,T}, ::Type{T′}) where {D,T,T′} = HomogeneousCell(SVector{D,T′}.(cell.cell_vectors), cell.label)
@inline switch_coord_type(cell::HomogeneousCell{D,T}, ::Type{T}) where {D,T} = cell
function switch_coord_type(cell::InhomogeneousCell{D,T}, ::Type{T′}) where {D,T,T′}
    new_cell_vectors = similar(cell.cell_vectors, SVector{D,T′})
    new_cell_vectors .= cell.cell_vectors
    return InhomogeneousCell(new_cell_vectors, cell.label)
end
@inline switch_coord_type(cell::InhomogeneousCell{D,T}, ::Type{T}) where {D,T} = cell

###
### Relative coordinate of two nodes in a cell

Base.@propagate_inbounds relative_coordinate(cell::AbstractCell, i1, i2) = cell[i1...] - cell[i2...]


text:
using JSON, CPLEX, JuMP

include("../src/JOH.jl")
include("../MDMKP/MDMKP.jl")

tight_problems = MDMKP.load_folder()
loose_problems = MDMKP.loosen.(tight_problems)
probs = vcat(tight_problems, loose_problems)
problems = MDMKP.set_decision.(probs)

function get_infeasibility(solution, problem) end

"""read the passed results directory (for one problem)
and return a (id.id, solution)"""
function load_problem_results(path)::Tuple{Int, Vector{Int}}
	highest_phase = max(map(f->parse(Int, f), readdir(path))...)
	final_data = read(joinpath(path, "$highest_phase", "results.json"), String)
	solution = JSON.parse(JSON.parse(final_data)[begin])
	problem_id = splitpath(path)[end]
	(parse(Int, problem_id), round.(solution))
end

"""load the results for the passed method and category"""
function load_method_dir(method, category::Char)
	problem_data_files = readdir("results/decision_tree/$category/$method/",
		join=true)
	load_problem_results.(problem_data_files)
end

_get_problem(id) = filter(p->p.id.id==id, problems)[begin]
function count_infeasibility(problem_id, solution)
	p = _get_problem(problem_id)
	n_real_vars = length(p.objective)
	n_artificial_vars = length(solution) - n_real_vars
	artificial_part = solution[begin:begin+n_artificial_vars-1]
	real_part = solution[end-n_real_vars+1:end]
	(problem_id, sum(abs.(artificial_part)))
end
count_inf(x) = count_infeasibility(x...)

res = load_method_dir("ssit", 'B')

output(count_inf.(res))

function output(d)
	for (p, inf) in d
		println("$p $inf")
	end
end

#get a specific result from the res var
_get_result(id) = first(filter(r->r[1] == id, res))

#get the base case result for the easiest problem, and load the problem itself
easiest_result = _get_result(1)
easiest_problem = _get_problem(1)

#solve the problem here
model = MDMKP.create_MIPS_model(easiest_problem)
set_optimizer(model, CPLEX.Optimizer)
optimize!(model)
objective_value(model)

#what is the solution?
computed_sol = value.(all_variables(model))
result_sol = easiest_result[2]

a = computed_sol[begin:begin+99]
b = result_sol[end-99:end]
c = result_sol[begin:begin+5]

max_stars_repo_name: Dibillilia/JuliaOptHeuristics

max_issues_repo_name: Dibillilia/JuliaOptHeuristics

max_forks_repo_name: Dibillilia/JuliaOptHeuristics


text:
using EquationsOfState
using Documenter

DocMeta.setdocmeta!(EquationsOfState, :DocTestSetup, :(using EquationsOfState); recursive=true)

makedocs(;
    modules=[EquationsOfState],
    authors="Qi Zhang <singularitti@outlook.com>",
    repo="https://github.com/MineralsCloud/EquationsOfState.jl/blob/{commit}{path}#{line}",
    sitename="EquationsOfState.jl",
    format=Documenter.HTML(;
        prettyurls=get(ENV, "CI", "false") == "true",
        canonical="https://MineralsCloud.github.io/EquationsOfState.jl",
        assets=String[],
    ),
    pages=[
        "Home" => "index.md",
    ],
)

deploydocs(;
    repo="github.com/MineralsCloud/EquationsOfState.jl",
)


text:
using ChainRulesOverloadGeneration
using ChainRulesCore: ChainRulesCore
using Documenter
using DocThemeIndigo
using Markdown

indigo = DocThemeIndigo.install(ChainRulesOverloadGeneration)

makedocs(
    modules=[ChainRulesOverloadGeneration],
    format=Documenter.HTML(
        prettyurls=false,
        assets=[indigo],
    ),
    sitename="ChainRules Overload Generation",
    authors="Lyndon White and other contributors",
    pages=[
        "Introduction" => "index.md",
        "Examples of making AD systems" => [
            "Forward Mode" => "examples/forward_mode.md",
            "Reverse Mode" => "examples/reverse_mode.md",
        ],
        "API" => "api.md",
       ],
    strict=true,
    checkdocs=:exports,
)

deploydocs(
    repo = "github.com/JuliaDiff/ChainRulesOverloadGeneration.jl.git",
    push_preview=true,
    devbranch="main",
)


text:
using LinearAlgebraicRepresentation
Lar = LinearAlgebraicRepresentation

using Plasm
p = PyCall.pyimport("pyplasm")

square = ([[0; 0] [0; 1] [1; 0] [1; 1]], [[1, 2, 3, 4]],
[[1,2], [1,3], [2,4], [3,4]])
V,FV,EV  =  square

function mkpol(verts::Lar.Points, cells::Lar.Cells)::Plasm.Hpc
   verts = Plasm.points2py(verts)
   cells = Plasm.cells2py(cells)
   return p["MKPOL"]([verts,cells,[]])
end

hpc = mkpol(V,EV)
p["VIEW"](hpc)


text:
module Contexts

using DataStructures: Stack

export TaskContextStorage, with_context, has_context, get_context

mutable struct ContextItem{T}
    value::T
    ContextItem(value::T) where {T} = new{T}(value)
end

struct TaskContextStorage
    storage::Dict{UInt64, Stack{ContextItem}}
    guard::ReentrantLock
    TaskContextStorage() = new(Dict{UInt64, Stack{ContextItem}}(), ReentrantLock())
end

#threads are runing as tasks too, so this id also unique for different threads
curr_task_id() = objectid(current_task())

#thread unsafe should be used under locks
get_curr_stack!(context::TaskContextStorage) = get!(context.storage, curr_task_id(), Stack{ContextItem}())

function Base.push!(context::TaskContextStorage, item::ContextItem)
    lock(context.guard) do
        push!(get_curr_stack!(context), item)
    end
end

function Base.pop!(context::TaskContextStorage)
    return lock(context.guard) do
        return pop!(get_curr_stack!(context))
    end
end

function Base.isempty(context::TaskContextStorage)
    return lock(context.guard) do
        return isempty(get_curr_stack!(context))
    end
end

function with_context(f, context::TaskContextStorage, item::ContextItem)
    push!(context, item)
    result = f()
    pop!(context)
    return result
end

with_context(f, context::TaskContextStorage, item) = with_context(f, context, ContextItem(item))

has_context(context::TaskContextStorage) = !isempty(context)

function get_context(context::TaskContextStorage)
    return lock(context.guard) do
        isempty(context) && throw(ArgumentError("context is not set"))
        return first(get_curr_stack!(context)).value
    end
end

end


text:
#-------------------------------------------------------------------
#* EMSO Model Library (EML) Copyright (C) 2004 - 2007 ALSOC.
#*
#* This LIBRARY is free software; you can distribute it and/or modify
#* it under the therms of the ALSOC FREE LICENSE as available at
#* http://www.enq.ufrgs.br/alsoc.
#*
#* EMSO Copyright (C) 2004 - 2007 ALSOC, original code
#* from http://www.rps.eng.br Copyright (C) 2002-2004.
#* All rights reserved.
#*
#* EMSO is distributed under the therms of the ALSOC LICENSE as
#* available at http://www.enq.ufrgs.br/alsoc.
#*
#*----------------------------------------------------------------------
#* Author: Maur좩cio Carvalho Maciel
#* $Id$
#*--------------------------------------------------------------------
type sepComp_n
	sepComp_n()=begin
		PP=outers.PP
		NComp=outers.NComp
		new(
			DanaPlugin(Dict{Symbol,Any}(
				:Brief=>"External Physical Properties",
				:Type=>"PP"
			)),
			DanaInteger(Dict{Symbol,Any}(
				:Brief=>"Number of chemical components",
				:Lower=>1
			)),
			DanaInteger(Dict{Symbol,Any}(
				:Brief=>"Number of Outlet Streams",
				:Lower=>1
			)),
			DanaInteger(Dict{Symbol,Any}(
				:Brief=>"Component specified",
				:Default=>1,
				:Lower=>1
			)),
			stream(Dict{Symbol,Any}(
				:Brief=>"Inlet stream",
				:PosX=>0,
				:PosY=>0.5,
				:Symbol=>"_{in}"
			)),
			fill(stream(Dict{Symbol,Any}(
				:Brief=>"Outlet streams",
				:PosX=>1,
				:PosY=>0.5059,
				:Symbol=>"_{out}"
			)),(NOutlet)),
			fill(fraction(Dict{Symbol,Any}(
				:Brief=>"Distribution of the Outlet streams",
				:Symbol=>"\\phi"
			)),(NOutlet)),
			fill(fraction(Dict{Symbol,Any}(
				:Brief=>"Recovery of the component specified",
				:Symbol=>"\\eta"
			)),(NOutlet)),
			[
				:(sum(Outlet.F) = Inlet.F),
				:(sum(Outlet([1:NOutlet-1]).z) = 1),
				:(sum(Outlet.F*Outlet.z([1:NComp])) = Inlet.F*Inlet.z([1:NComp])),
				:(Outlet([1:NOutlet]).F = Inlet.F*frac([1:NOutlet])),
				:(recovery([1:NOutlet])*Inlet.z(mainComp) = frac([1:NOutlet])*Outlet([1:NOutlet]).z(mainComp)),
				:(Outlet([1:NOutlet]).P = Inlet.P),
				:(Outlet([1:NOutlet]).h = (1-Outlet([1:NOutlet]).v)*PP.LiquidEnthalpy(Outlet([1:NOutlet]).T, Outlet([1:NOutlet]).P, Outlet([1:NOutlet]).z) + Outlet([1:NOutlet]).v*PP.VapourEnthalpy(Outlet([1:NOutlet]).T, Outlet([1:NOutlet]).P, Outlet([1:NOutlet]).z)),
				:(Outlet([1:NOutlet]).T = Inlet.T),
				:(Outlet([1:NOutlet]).v = PP.VapourFraction(Outlet([1:NOutlet]).T, Outlet([1:NOutlet]).P, Outlet([1:NOutlet]).z)),
			],
			[
				"Flow","Mol fraction normalisation","Composition","Flow","Recovery","Pressure","Enthalpy","Temperature","Vapourization Fraction",
			],
			[:PP,:NComp,:NOutlet,:mainComp,],
			[:Inlet,:Outlet,:frac,:recovery,]
		)
	end
	PP::DanaPlugin
	NComp::DanaInteger
	NOutlet::DanaInteger
	mainComp::DanaInteger
	Inlet::stream
	Outlet::Array{stream}
	frac::Array{fraction}
	recovery::Array{fraction}
	equations::Array{Expr,1}
	equationNames::Array{String,1}
	parameters::Array{Symbol,1}
	variables::Array{Symbol,1}
	attributes::Dict{Symbol,Any}
end
export sepComp_n
function setEquationFlow(in::sepComp_n)
	addEquation(1)
	addEquation(2)
	addEquation(3)
	addEquation(4)
	addEquation(5)
	addEquation(6)
	addEquation(7)
	addEquation(8)
	addEquation(9)
end
function atributes(in::sepComp_n,_::Dict{Symbol,Any})
	fields::Dict{Symbol,Any}=Dict{Symbol,Any}()
	fields[:Pallete]=false
	fields[:Icon]="icon/splitter_n"
	fields[:Brief]="Model of a separator of components (NOT Handled by the GUI)"
	fields[:Info]="== Assumptions ==
* thermodynamics equilibrium
* adiabatic

== Specify ==
* the inlet stream
* (NComp - 1) molar fractions to (Noutlet - 1) outlet streams
* (Noutlet - 1) frac (fraction of split of the outlet streams):

	frac(i) = (Mole Flow of the outlet stream i /
				Mole Flow of the inlet stream)
						where i = 1, 2,...,Noutlet

			or

* (Noutlet - 1) recovery (Recovery of the component specified in the outlet stream i):

  recovery(i) = (Mole Flow of the component specified in the Outlet stream i/
				Mole Flow of the component specified in the inlet stream)
						where i = 1, 2,...,Noutlet
"
	drive!(fields,_)
	return fields
end
sepComp_n(_::Dict{Symbol,Any})=begin
	newModel=sepComp_n()
	newModel.attributes=atributes(newModel,_)
	newModel
end


text:
# This file was generated, do not modify it. # hide
dist = SqL2Distance()
db = MatrixDatabase(X)
queries = MatrixDatabase(Q)
nothing # hide

max_stars_repo_name: sadit/SimilaritySearchDemos

max_issues_repo_name: sadit/SimilaritySearchDemos

max_forks_repo_name: sadit/SimilaritySearchDemos


text:
@info("Please allow up to 20 minutes for all tests to execute.")
import SeisIO
import SeisIO: get_svn
cd(dirname(pathof(SeisIO))*"/../test")
get_svn("https://github.com/jpjones76/SeisIO-TestData/trunk/SampleFiles", "SampleFiles")
include("local_restricted.jl")
include("test_helpers.jl")

# Announce test begin
test_start  = Dates.now()
ltestname   = 48
printstyled(stdout,
  string(test_start, ": tests begin, path = ", path, ", has_restricted = ", has_restricted, ", keep_log = ", keep_log, ", keep_samples = ", keep_samples, "\n"),
  color=:light_green,
  bold=true)

# Run all tests
# huehuehue grep "include(joinpath" runtests.jl | awk -F "(" '{print $3}' | awk -F "," {'print $1'}
for d in ["CoreUtils", "Types", "RandSeis", "Utils", "NativeIO", "DataFormats", "Processing", "Quake", "Web"]
  ld = length(d)
  ll = div(ltestname - ld - 2, 2)
  lr = ll + (isodd(ld) ? 1 : 0)
  printstyled(string("="^ll, " ", d, " ", "="^lr, "\n"), color=:cyan, bold=true)
  for i in readdir(path*"/"*d)
    f = joinpath(d,i)
    if endswith(i, ".jl")
      printstyled(lpad(" "*f, ltestname)*"\n", color=:cyan)
      write(out, string("\n\ntest ", f, "\n\n"))
      flush(out)
      include(f)
    end
  end
end

# Cleanup
include("cleanup.jl")
if keep_samples == false
  include("rm_samples.jl")
end
if !keep_log
  try
    rm("runtests.log")
  catch err
    @warn(string("can't remove runtests.log; threw err", err))
  end
end

# Announce tests end
test_end = Dates.now()
δt = 0.001*(test_end-test_start).value
mm = round(Int, div(δt, 60))
ss = rem(δt, 60)
printstyled(string(test_end, ": tests end, elapsed time (mm:ss.μμμ) = ",
                          @sprintf("%02i", mm), ":",
                          @sprintf("%06.3f", ss), "\n"), color=:light_green, bold=true)
printstyled("To run some data acquisition examples, execute this command: include(\"", path, "/examples.jl\").\n", color=:cyan, bold=true)


text:
"""
Pyndl object.
"""
struct Pyndl_Weight_Struct
    cues::Vector{String}
    outcomes::Vector{String}
    weight::Matrix{Float64}
end

"""
    pyndl(data_path)

Perform pyndl.
"""
function pyndl(
    data_path;
    alpha = 0.1,
    betas = (0.1, 0.1),
)

    ndl = pyimport("pyndl.ndl")

    weights_py = ndl.ndl(
        events = data_path,
        alpha = alpha,
        betas = betas,
        method = "openmp",
        remove_duplicates = true,
    )

    unwrap_xarray(weights_py)

end

function unwrap_xarray(weights)
    coords = weights.coords.to_dataset()
    cues = [i for i in coords.cues.data]
    outcomes = [i for i in coords.outcomes.data]
    weights = weights.data

    Pyndl_Weight_Struct(cues, outcomes, weights)
end


text:
@testset "SAM" begin
    samdir = path_of_format("SAM")

    @testset "MetaInfo" begin
        metainfo = SAM.MetaInfo()
        @test !isfilled(metainfo)
        @test occursin("not filled", repr(metainfo))

        metainfo = SAM.MetaInfo("CO", "some comment (parens)")
        @test isfilled(metainfo)
        @test string(metainfo) == "@CO\tsome comment (parens)"
        @test occursin("CO", repr(metainfo))
        @test SAM.tag(metainfo) == "CO"
        @test SAM.value(metainfo) == "some comment (parens)"
        @test_throws ArgumentError keys(metainfo)
        @test_throws ArgumentError values(metainfo)

        metainfo = SAM.MetaInfo("HD", ["VN" => "1.0", "SO" => "coordinate"])
        @test isfilled(metainfo)
        @test string(metainfo) == "@HD\tVN:1.0\tSO:coordinate"
        @test occursin("HD", repr(metainfo))
        @test SAM.tag(metainfo) == "HD"
        @test SAM.value(metainfo) == "VN:1.0\tSO:coordinate"
        @test keys(metainfo) == ["VN", "SO"]
        @test values(metainfo) == ["1.0", "coordinate"]
        @test SAM.keyvalues(metainfo) == ["VN" => "1.0", "SO" => "coordinate"]
        @test haskey(metainfo, "VN")
        @test haskey(metainfo, "SO")
        @test !haskey(metainfo, "GO")
        @test metainfo["VN"] == "1.0"
        @test metainfo["SO"] == "coordinate"
        @test_throws KeyError metainfo["GO"]
    end

    @testset "Header" begin
        header = SAM.Header()
        @test isempty(header)
        push!(header, SAM.MetaInfo("@HD\tVN:1.0\tSO:coordinate"))
        @test !isempty(header)
        @test length(header) == 1
        push!(header, SAM.MetaInfo("@CO\tsome comment"))
        @test length(header) == 2
        @test isa(collect(header), Vector{SAM.MetaInfo})
    end

    @testset "Record" begin
        record = SAM.Record()
        @test !isfilled(record)
        @test !SAM.ismapped(record)
        @test repr(record) == "XAM.SAM.Record: <not filled>"
        @test_throws ArgumentError SAM.flag(record)

        record = SAM.Record("r001\t99\tchr1\t7\t30\t8M2I4M1D3M\t=\t37\t39\tTTAGATAAAGGATACTG\t*")
        @test isfilled(record)
        @test occursin(r"^XAM.SAM.Record:\n", repr(record))
        @test SAM.ismapped(record)
        @test SAM.isprimary(record)
        @test SAM.hastempname(record)
        @test SAM.tempname(record) == "r001"
        @test SAM.hasflag(record)
        @test SAM.flag(record) === UInt16(99)
        @test SAM.hasrefname(record)
        @test SAM.refname(record) == "chr1"
        @test SAM.hasposition(record)
        @test SAM.position(record) === 7
        @test SAM.hasmappingquality(record)
        @test SAM.mappingquality(record) === UInt8(30)
        @test SAM.hascigar(record)
        @test SAM.cigar(record) == "8M2I4M1D3M"
        @test SAM.hasnextrefname(record)
        @test SAM.nextrefname(record) == "="
        @test SAM.hasnextposition(record)
        @test SAM.nextposition(record) === 37
        @test SAM.hastemplength(record)
        @test SAM.templength(record) === 39
        @test SAM.hassequence(record)
        @test SAM.sequence(record) == dna"TTAGATAAAGGATACTG"
        @test !SAM.hasquality(record)
        @test_throws MissingFieldException SAM.quality(record)
    end

    @testset "Reader" begin
        reader = open(SAM.Reader, joinpath(samdir, "ce#1.sam"))
        @test isa(reader, SAM.Reader)
        @test eltype(reader) === SAM.Record

        # header
        h = header(reader)
        @test string.(findall(header(reader), "SQ")) == ["@SQ\tSN:CHROMOSOME_I\tLN:1009800"]

        # first record
        record = SAM.Record()
        read!(reader, record)
        @test SAM.ismapped(record)
        @test SAM.refname(record) == "CHROMOSOME_I"
        @test SAM.position(record) == leftposition(record) == 2
        @test SAM.rightposition(record) == rightposition(record) == 102
        @test SAM.tempname(record) == seqname(record) == "SRR065390.14978392"
        @test SAM.sequence(record) == sequence(record) == dna"CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA"
        @test SAM.sequence(String, record)          ==    "CCTAGCCCTAACCCTAACCCTAACCCTAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAAGCCTAA"
        @test SAM.seqlength(record) == 100
        @test SAM.quality(record)         == (b"#############################@B?8B?BA@@DDBCDDCBC@CDCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" .- 33)
        @test SAM.quality(String, record) ==   "#############################@B?8B?BA@@DDBCDDCBC@CDCDCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC"
        @test SAM.flag(record) == 16
        @test SAM.cigar(record) == "27M1D73M"
        @test SAM.alignment(record) == Alignment([
            AlignmentAnchor(  0,   1, OP_START),
            AlignmentAnchor( 27,  28, OP_MATCH),
            AlignmentAnchor( 27,  29, OP_DELETE),
            AlignmentAnchor(100, 102, OP_MATCH)])
        @test record["XG"] == 1
        @test record["XM"] == 5
        @test record["XN"] == 0
        @test record["XO"] == 1
        @test record["AS"] == -18
        @test record["XS"] == -18
        @test record["YT"] == "UU"
        @test eof(reader)
        close(reader)

        # rightposition (also implicitly alignlength)
        records = collect(open(SAM.Reader, joinpath(samdir, "ce#5b.sam")))
        @test SAM.rightposition(records[6]) == rightposition(records[6]) == 83

        # iterator
        @test length(collect(open(SAM.Reader, joinpath(samdir, "ce#1.sam")))) == 1
        @test length(collect(open(SAM.Reader, joinpath(samdir, "ce#2.sam")))) == 2

        # IOStream
        @test length(collect(SAM.Reader(open(joinpath(samdir, "ce#1.sam"))))) == 1
        @test length(collect(SAM.Reader(open(joinpath(samdir, "ce#2.sam"))))) == 2
    end

    @testset "Round trip" begin
        function compare_records(xs, ys)
            if length(xs) != length(ys)
                return false
            end
            for (x, y) in zip(xs, ys)
                if x.data[x.filled] != y.data[y.filled]
                    return false
                end
            end
            return true
        end
        for specimen in list_valid_specimens("SAM")
            filepath = joinpath(samdir, filename(specimen))
            mktemp() do path, io
                # copy
                reader = open(SAM.Reader, filepath)

                header_original = header(reader)

                writer = SAM.Writer(io, header_original)

                records = SAM.Record[]
                for record in reader
                    push!(records, record)
                    write(writer, record)
                end

                close(reader)
                close(writer)

                reader = open(SAM.Reader, path)

                @test header(reader) == header_original
                @test compare_records(collect(reader), records)

                close(reader)

            end
        end
    end

    @testset "In-Place-Reading Pattern" begin

        file_sam = joinpath(samdir, "ce#5b.sam")

        records = open(collect, SAM.Reader, file_sam)

        reader = open(SAM.Reader, file_sam)
        record = SAM.Record()
        i = 0
        while !eof(reader)
            empty!(record) # Reset the record.
            read!(reader, record)

            i = i + 1

            @test records[i] == record

        end

        close(reader)

        # Test blank file.
        file_sam = joinpath(samdir, "xx#blank.sam")

        records = open(collect, SAM.Reader, file_sam)
        @test records == []

    end
end