text:
# Julia wrapper for header: ../deps/usr/include/fann.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0

function fann_set_error_log(errdat::Ptr{fann_error},log_file::Ptr{FILE})
    ccall((:fann_set_error_log,libfann),Void,(Ptr{fann_error},Ptr{FILE}),errdat,log_file)
end

function fann_get_errno(errdat::Ptr{fann_error})
    ccall((:fann_get_errno,libfann),Cint,(Ptr{fann_error},),errdat)
end

function fann_reset_errno(errdat::Ptr{fann_error})
    ccall((:fann_reset_errno,libfann),Void,(Ptr{fann_error},),errdat)
end

function fann_reset_errstr(errdat::Ptr{fann_error})
    ccall((:fann_reset_errstr,libfann),Void,(Ptr{fann_error},),errdat)
end

function fann_get_errstr(errdat::Ptr{fann_error})
    ccall((:fann_get_errstr,libfann),Ptr{Uint8},(Ptr{fann_error},),errdat)
end

function fann_print_error(errdat::Ptr{fann_error})
    ccall((:fann_print_error,libfann),Void,(Ptr{fann_error},),errdat)
end

function fann_allocate_structure(num_layers::Uint32)
    ccall((:fann_allocate_structure,libfann),Ptr{fann},(Uint32,),num_layers)
end

function fann_allocate_neurons(ann::Ptr{fann})
    ccall((:fann_allocate_neurons,libfann),Void,(Ptr{fann},),ann)
end

function fann_allocate_connections(ann::Ptr{fann})
    ccall((:fann_allocate_connections,libfann),Void,(Ptr{fann},),ann)
end

function fann_save_internal(ann::Ptr{fann},configuration_file::Ptr{Uint8},save_as_fixed::Uint32)
    ccall((:fann_save_internal,libfann),Cint,(Ptr{fann},Ptr{Uint8},Uint32),ann,configuration_file,save_as_fixed)
end

function fann_save_internal_fd(ann::Ptr{fann},conf::Ptr{FILE},configuration_file::Ptr{Uint8},save_as_fixed::Uint32)
    ccall((:fann_save_internal_fd,libfann),Cint,(Ptr{fann},Ptr{FILE},Ptr{Uint8},Uint32),ann,conf,configuration_file,save_as_fixed)
end

function fann_save_train_internal(data::Ptr{fann_train_data},filename::Ptr{Uint8},save_as_fixed::Uint32,decimal_point::Uint32)
    ccall((:fann_save_train_internal,libfann),Cint,(Ptr{fann_train_data},Ptr{Uint8},Uint32,Uint32),data,filename,save_as_fixed,decimal_point)
end

function fann_save_train_internal_fd(data::Ptr{fann_train_data},file::Ptr{FILE},filename::Ptr{Uint8},save_as_fixed::Uint32,decimal_point::Uint32)
    ccall((:fann_save_train_internal_fd,libfann),Cint,(Ptr{fann_train_data},Ptr{FILE},Ptr{Uint8},Uint32,Uint32),data,file,filename,save_as_fixed,decimal_point)
end

function fann_update_stepwise(ann::Ptr{fann})
    ccall((:fann_update_stepwise,libfann),Void,(Ptr{fann},),ann)
end

function fann_init_error_data(errdat::Ptr{fann_error})
    ccall((:fann_init_error_data,libfann),Void,(Ptr{fann_error},),errdat)
end

function fann_create_from_fd(conf::Ptr{FILE},configuration_file::Ptr{Uint8})
    ccall((:fann_create_from_fd,libfann),Ptr{fann},(Ptr{FILE},Ptr{Uint8}),conf,configuration_file)
end

function fann_read_train_from_fd(file::Ptr{FILE},filename::Ptr{Uint8})
    ccall((:fann_read_train_from_fd,libfann),Ptr{fann_train_data},(Ptr{FILE},Ptr{Uint8}),file,filename)
end

function fann_compute_MSE(ann::Ptr{fann},desired_output::Ptr{fann_type})
    ccall((:fann_compute_MSE,libfann),Void,(Ptr{fann},Ptr{fann_type}),ann,desired_output)
end

function fann_update_output_weights(ann::Ptr{fann})
    ccall((:fann_update_output_weights,libfann),Void,(Ptr{fann},),ann)
end

function fann_backpropagate_MSE(ann::Ptr{fann})
    ccall((:fann_backpropagate_MSE,libfann),Void,(Ptr{fann},),ann)
end

function fann_update_weights(ann::Ptr{fann})
    ccall((:fann_update_weights,libfann),Void,(Ptr{fann},),ann)
end

function fann_update_slopes_batch(ann::Ptr{fann},layer_begin::Ptr{fann_layer},layer_end::Ptr{fann_layer})
    ccall((:fann_update_slopes_batch,libfann),Void,(Ptr{fann},Ptr{fann_layer},Ptr{fann_layer}),ann,layer_begin,layer_end)
end

function fann_update_weights_quickprop(ann::Ptr{fann},num_data::Uint32,first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_quickprop,libfann),Void,(Ptr{fann},Uint32,Uint32,Uint32),ann,num_data,first_weight,past_end)
end

function fann_update_weights_batch(ann::Ptr{fann},num_data::Uint32,first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_batch,libfann),Void,(Ptr{fann},Uint32,Uint32,Uint32),ann,num_data,first_weight,past_end)
end

function fann_update_weights_irpropm(ann::Ptr{fann},first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_irpropm,libfann),Void,(Ptr{fann},Uint32,Uint32),ann,first_weight,past_end)
end

function fann_update_weights_sarprop(ann::Ptr{fann},epoch::Uint32,first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_sarprop,libfann),Void,(Ptr{fann},Uint32,Uint32,Uint32),ann,epoch,first_weight,past_end)
end

function fann_clear_train_arrays(ann::Ptr{fann})
    ccall((:fann_clear_train_arrays,libfann),Void,(Ptr{fann},),ann)
end

function fann_activation(ann::Ptr{fann},activation_function::Uint32,steepness::fann_type,value::fann_type)
    ccall((:fann_activation,libfann),fann_type,(Ptr{fann},Uint32,fann_type,fann_type),ann,activation_function,steepness,value)
end

function fann_activation_derived(activation_function::Uint32,steepness::fann_type,value::fann_type,sum::fann_type)
    ccall((:fann_activation_derived,libfann),fann_type,(Uint32,fann_type,fann_type,fann_type),activation_function,steepness,value,sum)
end

function fann_desired_error_reached(ann::Ptr{fann},desired_error::Cfloat)
    ccall((:fann_desired_error_reached,libfann),Cint,(Ptr{fann},Cfloat),ann,desired_error)
end

function fann_train_outputs(ann::Ptr{fann},data::Ptr{fann_train_data},desired_error::Cfloat)
    ccall((:fann_train_outputs,libfann),Cint,(Ptr{fann},Ptr{fann_train_data},Cfloat),ann,data,desired_error)
end

function fann_train_outputs_epoch(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_train_outputs_epoch,libfann),Cfloat,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_train_candidates(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_train_candidates,libfann),Cint,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_train_candidates_epoch(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_train_candidates_epoch,libfann),fann_type,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_install_candidate(ann::Ptr{fann})
    ccall((:fann_install_candidate,libfann),Void,(Ptr{fann},),ann)
end

function fann_check_input_output_sizes(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_check_input_output_sizes,libfann),Cint,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_initialize_candidates(ann::Ptr{fann})
    ccall((:fann_initialize_candidates,libfann),Cint,(Ptr{fann},),ann)
end

function fann_set_shortcut_connections(ann::Ptr{fann})
    ccall((:fann_set_shortcut_connections,libfann),Void,(Ptr{fann},),ann)
end

function fann_allocate_scale(ann::Ptr{fann})
    ccall((:fann_allocate_scale,libfann),Cint,(Ptr{fann},),ann)
end

function fann_scale_data_to_range(data::Ptr{Ptr{fann_type}},num_data::Uint32,num_elem::Uint32,old_min::fann_type,old_max::fann_type,new_min::fann_type,new_max::fann_type)
    ccall((:fann_scale_data_to_range,libfann),Void,(Ptr{Ptr{fann_type}},Uint32,Uint32,fann_type,fann_type,fann_type,fann_type),data,num_data,num_elem,old_min,old_max,new_min,new_max)
end

function fann_train(ann::Ptr{fann},input::Ptr{fann_type},desired_output::Ptr{fann_type})
    ccall((:fann_train,libfann),Void,(Ptr{fann},Ptr{fann_type},Ptr{fann_type}),ann,input,desired_output)
end

function fann_test(ann::Ptr{fann},input::Ptr{fann_type},desired_output::Ptr{fann_type})
    ccall((:fann_test,libfann),Ptr{fann_type},(Ptr{fann},Ptr{fann_type},Ptr{fann_type}),ann,input,desired_output)
end

function fann_get_MSE(ann::Ptr{fann})
    ccall((:fann_get_MSE,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_get_bit_fail(ann::Ptr{fann})
    ccall((:fann_get_bit_fail,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_reset_MSE(ann::Ptr{fann})
    ccall((:fann_reset_MSE,libfann),Void,(Ptr{fann},),ann)
end

function fann_train_on_data(ann::Ptr{fann},data::Ptr{fann_train_data},max_epochs::Uint32,epochs_between_reports::Uint32,desired_error::Cfloat)
    ccall((:fann_train_on_data,libfann),Void,(Ptr{fann},Ptr{fann_train_data},Uint32,Uint32,Cfloat),ann,data,max_epochs,epochs_between_reports,desired_error)
end

function fann_train_on_file(ann::Ptr{fann},filename::Ptr{Uint8},max_epochs::Uint32,epochs_between_reports::Uint32,desired_error::Cfloat)
    ccall((:fann_train_on_file,libfann),Void,(Ptr{fann},Ptr{Uint8},Uint32,Uint32,Cfloat),ann,filename,max_epochs,epochs_between_reports,desired_error)
end

function fann_train_epoch(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_train_epoch,libfann),Cfloat,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_test_data(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_test_data,libfann),Cfloat,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_read_train_from_file(filename::Ptr{Uint8})
    ccall((:fann_read_train_from_file,libfann),Ptr{fann_train_data},(Ptr{Uint8},),filename)
end

function fann_create_train(num_data::Uint32,num_input::Uint32,num_output::Uint32)
    ccall((:fann_create_train,libfann),Ptr{fann_train_data},(Uint32,Uint32,Uint32),num_data,num_input,num_output)
end

function fann_create_train_pointer_array(num_data::Uint32,num_input::Uint32,input::Ptr{Ptr{fann_type}},num_output::Uint32,output::Ptr{Ptr{fann_type}})
    ccall((:fann_create_train_pointer_array,libfann),Ptr{fann_train_data},(Uint32,Uint32,Ptr{Ptr{fann_type}},Uint32,Ptr{Ptr{fann_type}}),num_data,num_input,input,num_output,output)
end

function fann_create_train_array(num_data::Uint32,num_input::Uint32,input::Ptr{fann_type},num_output::Uint32,output::Ptr{fann_type})
    ccall((:fann_create_train_array,libfann),Ptr{fann_train_data},(Uint32,Uint32,Ptr{fann_type},Uint32,Ptr{fann_type}),num_data,num_input,input,num_output,output)
end

function fann_create_train_from_callback(num_data::Uint32,num_input::Uint32,num_output::Uint32,user_function::Ptr{Void})
    ccall((:fann_create_train_from_callback,libfann),Ptr{fann_train_data},(Uint32,Uint32,Uint32,Ptr{Void}),num_data,num_input,num_output,user_function)
end

function fann_destroy_train(train_data::Ptr{fann_train_data})
    ccall((:fann_destroy_train,libfann),Void,(Ptr{fann_train_data},),train_data)
end

function fann_get_train_input(data::Ptr{fann_train_data},position::Uint32)
    ccall((:fann_get_train_input,libfann),Ptr{fann_type},(Ptr{fann_train_data},Uint32),data,position)
end

function fann_get_train_output(data::Ptr{fann_train_data},position::Uint32)
    ccall((:fann_get_train_output,libfann),Ptr{fann_type},(Ptr{fann_train_data},Uint32),data,position)
end

function fann_shuffle_train_data(train_data::Ptr{fann_train_data})
    ccall((:fann_shuffle_train_data,libfann),Void,(Ptr{fann_train_data},),train_data)
end

function fann_scale_train(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_scale_train,libfann),Void,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_descale_train(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_descale_train,libfann),Void,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_set_input_scaling_params(ann::Ptr{fann},data::Ptr{fann_train_data},new_input_min::Cfloat,new_input_max::Cfloat)
    ccall((:fann_set_input_scaling_params,libfann),Cint,(Ptr{fann},Ptr{fann_train_data},Cfloat,Cfloat),ann,data,new_input_min,new_input_max)
end

function fann_set_output_scaling_params(ann::Ptr{fann},data::Ptr{fann_train_data},new_output_min::Cfloat,new_output_max::Cfloat)
    ccall((:fann_set_output_scaling_params,libfann),Cint,(Ptr{fann},Ptr{fann_train_data},Cfloat,Cfloat),ann,data,new_output_min,new_output_max)
end

function fann_set_scaling_params(ann::Ptr{fann},data::Ptr{fann_train_data},new_input_min::Cfloat,new_input_max::Cfloat,new_output_min::Cfloat,new_output_max::Cfloat)
    ccall((:fann_set_scaling_params,libfann),Cint,(Ptr{fann},Ptr{fann_train_data},Cfloat,Cfloat,Cfloat,Cfloat),ann,data,new_input_min,new_input_max,new_output_min,new_output_max)
end

function fann_clear_scaling_params(ann::Ptr{fann})
    ccall((:fann_clear_scaling_params,libfann),Cint,(Ptr{fann},),ann)
end

function fann_scale_input(ann::Ptr{fann},input_vector::Ptr{fann_type})
    ccall((:fann_scale_input,libfann),Void,(Ptr{fann},Ptr{fann_type}),ann,input_vector)
end

function fann_scale_output(ann::Ptr{fann},output_vector::Ptr{fann_type})
    ccall((:fann_scale_output,libfann),Void,(Ptr{fann},Ptr{fann_type}),ann,output_vector)
end

function fann_descale_input(ann::Ptr{fann},input_vector::Ptr{fann_type})
    ccall((:fann_descale_input,libfann),Void,(Ptr{fann},Ptr{fann_type}),ann,input_vector)
end

function fann_descale_output(ann::Ptr{fann},output_vector::Ptr{fann_type})
    ccall((:fann_descale_output,libfann),Void,(Ptr{fann},Ptr{fann_type}),ann,output_vector)
end

function fann_scale_input_train_data(train_data::Ptr{fann_train_data},new_min::fann_type,new_max::fann_type)
    ccall((:fann_scale_input_train_data,libfann),Void,(Ptr{fann_train_data},fann_type,fann_type),train_data,new_min,new_max)
end

function fann_scale_output_train_data(train_data::Ptr{fann_train_data},new_min::fann_type,new_max::fann_type)
    ccall((:fann_scale_output_train_data,libfann),Void,(Ptr{fann_train_data},fann_type,fann_type),train_data,new_min,new_max)
end

function fann_scale_train_data(train_data::Ptr{fann_train_data},new_min::fann_type,new_max::fann_type)
    ccall((:fann_scale_train_data,libfann),Void,(Ptr{fann_train_data},fann_type,fann_type),train_data,new_min,new_max)
end

function fann_merge_train_data(data1::Ptr{fann_train_data},data2::Ptr{fann_train_data})
    ccall((:fann_merge_train_data,libfann),Ptr{fann_train_data},(Ptr{fann_train_data},Ptr{fann_train_data}),data1,data2)
end

function fann_duplicate_train_data(data::Ptr{fann_train_data})
    ccall((:fann_duplicate_train_data,libfann),Ptr{fann_train_data},(Ptr{fann_train_data},),data)
end

function fann_subset_train_data(data::Ptr{fann_train_data},pos::Uint32,length::Uint32)
    ccall((:fann_subset_train_data,libfann),Ptr{fann_train_data},(Ptr{fann_train_data},Uint32,Uint32),data,pos,length)
end

function fann_length_train_data(data::Ptr{fann_train_data})
    ccall((:fann_length_train_data,libfann),Uint32,(Ptr{fann_train_data},),data)
end

function fann_num_input_train_data(data::Ptr{fann_train_data})
    ccall((:fann_num_input_train_data,libfann),Uint32,(Ptr{fann_train_data},),data)
end

function fann_num_output_train_data(data::Ptr{fann_train_data})
    ccall((:fann_num_output_train_data,libfann),Uint32,(Ptr{fann_train_data},),data)
end

function fann_save_train(data::Ptr{fann_train_data},filename::Ptr{Uint8})
    ccall((:fann_save_train,libfann),Cint,(Ptr{fann_train_data},Ptr{Uint8}),data,filename)
end

function fann_save_train_to_fixed(data::Ptr{fann_train_data},filename::Ptr{Uint8},decimal_point::Uint32)
    ccall((:fann_save_train_to_fixed,libfann),Cint,(Ptr{fann_train_data},Ptr{Uint8},Uint32),data,filename,decimal_point)
end

function fann_get_training_algorithm(ann::Ptr{fann})
    ccall((:fann_get_training_algorithm,libfann),Cint,(Ptr{fann},),ann)
end

function fann_set_training_algorithm(ann::Ptr{fann},training_algorithm::fann_train_enum)
    ccall((:fann_set_training_algorithm,libfann),Void,(Ptr{fann},fann_train_enum),ann,training_algorithm)
end

function fann_get_learning_rate(ann::Ptr{fann})
    ccall((:fann_get_learning_rate,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_learning_rate(ann::Ptr{fann},learning_rate::Cfloat)
    ccall((:fann_set_learning_rate,libfann),Void,(Ptr{fann},Cfloat),ann,learning_rate)
end

function fann_get_learning_momentum(ann::Ptr{fann})
    ccall((:fann_get_learning_momentum,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_learning_momentum(ann::Ptr{fann},learning_momentum::Cfloat)
    ccall((:fann_set_learning_momentum,libfann),Void,(Ptr{fann},Cfloat),ann,learning_momentum)
end

function fann_get_activation_function(ann::Ptr{fann},layer::Cint,neuron::Cint)
    ccall((:fann_get_activation_function,libfann),Cint,(Ptr{fann},Cint,Cint),ann,layer,neuron)
end

function fann_set_activation_function(ann::Ptr{fann},activation_function::fann_activationfunc_enum,layer::Cint,neuron::Cint)
    ccall((:fann_set_activation_function,libfann),Void,(Ptr{fann},fann_activationfunc_enum,Cint,Cint),ann,activation_function,layer,neuron)
end

function fann_set_activation_function_layer(ann::Ptr{fann},activation_function::fann_activationfunc_enum,layer::Cint)
    ccall((:fann_set_activation_function_layer,libfann),Void,(Ptr{fann},fann_activationfunc_enum,Cint),ann,activation_function,layer)
end

function fann_set_activation_function_hidden(ann::Ptr{fann},activation_function::fann_activationfunc_enum)
    ccall((:fann_set_activation_function_hidden,libfann),Void,(Ptr{fann},fann_activationfunc_enum),ann,activation_function)
end

function fann_set_activation_function_output(ann::Ptr{fann},activation_function::fann_activationfunc_enum)
    ccall((:fann_set_activation_function_output,libfann),Void,(Ptr{fann},fann_activationfunc_enum),ann,activation_function)
end

function fann_get_activation_steepness(ann::Ptr{fann},layer::Cint,neuron::Cint)
    ccall((:fann_get_activation_steepness,libfann),fann_type,(Ptr{fann},Cint,Cint),ann,layer,neuron)
end

function fann_set_activation_steepness(ann::Ptr{fann},steepness::fann_type,layer::Cint,neuron::Cint)
    ccall((:fann_set_activation_steepness,libfann),Void,(Ptr{fann},fann_type,Cint,Cint),ann,steepness,layer,neuron)
end

function fann_set_activation_steepness_layer(ann::Ptr{fann},steepness::fann_type,layer::Cint)
    ccall((:fann_set_activation_steepness_layer,libfann),Void,(Ptr{fann},fann_type,Cint),ann,steepness,layer)
end

function fann_set_activation_steepness_hidden(ann::Ptr{fann},steepness::fann_type)
    ccall((:fann_set_activation_steepness_hidden,libfann),Void,(Ptr{fann},fann_type),ann,steepness)
end

function fann_set_activation_steepness_output(ann::Ptr{fann},steepness::fann_type)
    ccall((:fann_set_activation_steepness_output,libfann),Void,(Ptr{fann},fann_type),ann,steepness)
end

function fann_get_train_error_function(ann::Ptr{fann})
    ccall((:fann_get_train_error_function,libfann),Cint,(Ptr{fann},),ann)
end

function fann_set_train_error_function(ann::Ptr{fann},train_error_function::fann_errorfunc_enum)
    ccall((:fann_set_train_error_function,libfann),Void,(Ptr{fann},fann_errorfunc_enum),ann,train_error_function)
end

function fann_get_train_stop_function(ann::Ptr{fann})
    ccall((:fann_get_train_stop_function,libfann),Cint,(Ptr{fann},),ann)
end

function fann_set_train_stop_function(ann::Ptr{fann},train_stop_function::fann_stopfunc_enum)
    ccall((:fann_set_train_stop_function,libfann),Void,(Ptr{fann},fann_stopfunc_enum),ann,train_stop_function)
end

function fann_get_bit_fail_limit(ann::Ptr{fann})
    ccall((:fann_get_bit_fail_limit,libfann),fann_type,(Ptr{fann},),ann)
end

function fann_set_bit_fail_limit(ann::Ptr{fann},bit_fail_limit::fann_type)
    ccall((:fann_set_bit_fail_limit,libfann),Void,(Ptr{fann},fann_type),ann,bit_fail_limit)
end

function fann_set_callback(ann::Ptr{fann},callback::fann_callback_type)
    ccall((:fann_set_callback,libfann),Void,(Ptr{fann},fann_callback_type),ann,callback)
end

function fann_get_quickprop_decay(ann::Ptr{fann})
    ccall((:fann_get_quickprop_decay,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_quickprop_decay(ann::Ptr{fann},quickprop_decay::Cfloat)
    ccall((:fann_set_quickprop_decay,libfann),Void,(Ptr{fann},Cfloat),ann,quickprop_decay)
end

function fann_get_quickprop_mu(ann::Ptr{fann})
    ccall((:fann_get_quickprop_mu,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_quickprop_mu(ann::Ptr{fann},quickprop_mu::Cfloat)
    ccall((:fann_set_quickprop_mu,libfann),Void,(Ptr{fann},Cfloat),ann,quickprop_mu)
end

function fann_get_rprop_increase_factor(ann::Ptr{fann})
    ccall((:fann_get_rprop_increase_factor,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_rprop_increase_factor(ann::Ptr{fann},rprop_increase_factor::Cfloat)
    ccall((:fann_set_rprop_increase_factor,libfann),Void,(Ptr{fann},Cfloat),ann,rprop_increase_factor)
end

function fann_get_rprop_decrease_factor(ann::Ptr{fann})
    ccall((:fann_get_rprop_decrease_factor,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_rprop_decrease_factor(ann::Ptr{fann},rprop_decrease_factor::Cfloat)
    ccall((:fann_set_rprop_decrease_factor,libfann),Void,(Ptr{fann},Cfloat),ann,rprop_decrease_factor)
end

function fann_get_rprop_delta_min(ann::Ptr{fann})
    ccall((:fann_get_rprop_delta_min,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_rprop_delta_min(ann::Ptr{fann},rprop_delta_min::Cfloat)
    ccall((:fann_set_rprop_delta_min,libfann),Void,(Ptr{fann},Cfloat),ann,rprop_delta_min)
end

function fann_get_rprop_delta_max(ann::Ptr{fann})
    ccall((:fann_get_rprop_delta_max,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_rprop_delta_max(ann::Ptr{fann},rprop_delta_max::Cfloat)
    ccall((:fann_set_rprop_delta_max,libfann),Void,(Ptr{fann},Cfloat),ann,rprop_delta_max)
end

function fann_get_rprop_delta_zero(ann::Ptr{fann})
    ccall((:fann_get_rprop_delta_zero,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_rprop_delta_zero(ann::Ptr{fann},rprop_delta_max::Cfloat)
    ccall((:fann_set_rprop_delta_zero,libfann),Void,(Ptr{fann},Cfloat),ann,rprop_delta_max)
end

function fann_get_sarprop_weight_decay_shift(ann::Ptr{fann})
    ccall((:fann_get_sarprop_weight_decay_shift,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_sarprop_weight_decay_shift(ann::Ptr{fann},sarprop_weight_decay_shift::Cfloat)
    ccall((:fann_set_sarprop_weight_decay_shift,libfann),Void,(Ptr{fann},Cfloat),ann,sarprop_weight_decay_shift)
end

function fann_get_sarprop_step_error_threshold_factor(ann::Ptr{fann})
    ccall((:fann_get_sarprop_step_error_threshold_factor,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_sarprop_step_error_threshold_factor(ann::Ptr{fann},sarprop_step_error_threshold_factor::Cfloat)
    ccall((:fann_set_sarprop_step_error_threshold_factor,libfann),Void,(Ptr{fann},Cfloat),ann,sarprop_step_error_threshold_factor)
end

function fann_get_sarprop_step_error_shift(ann::Ptr{fann})
    ccall((:fann_get_sarprop_step_error_shift,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_sarprop_step_error_shift(ann::Ptr{fann},sarprop_step_error_shift::Cfloat)
    ccall((:fann_set_sarprop_step_error_shift,libfann),Void,(Ptr{fann},Cfloat),ann,sarprop_step_error_shift)
end

function fann_get_sarprop_temperature(ann::Ptr{fann})
    ccall((:fann_get_sarprop_temperature,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_sarprop_temperature(ann::Ptr{fann},sarprop_temperature::Cfloat)
    ccall((:fann_set_sarprop_temperature,libfann),Void,(Ptr{fann},Cfloat),ann,sarprop_temperature)
end

function fann_cascadetrain_on_data(ann::Ptr{fann},data::Ptr{fann_train_data},max_neurons::Uint32,neurons_between_reports::Uint32,desired_error::Cfloat)
    ccall((:fann_cascadetrain_on_data,libfann),Void,(Ptr{fann},Ptr{fann_train_data},Uint32,Uint32,Cfloat),ann,data,max_neurons,neurons_between_reports,desired_error)
end

function fann_cascadetrain_on_file(ann::Ptr{fann},filename::Ptr{Uint8},max_neurons::Uint32,neurons_between_reports::Uint32,desired_error::Cfloat)
    ccall((:fann_cascadetrain_on_file,libfann),Void,(Ptr{fann},Ptr{Uint8},Uint32,Uint32,Cfloat),ann,filename,max_neurons,neurons_between_reports,desired_error)
end

function fann_get_cascade_output_change_fraction(ann::Ptr{fann})
    ccall((:fann_get_cascade_output_change_fraction,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_cascade_output_change_fraction(ann::Ptr{fann},cascade_output_change_fraction::Cfloat)
    ccall((:fann_set_cascade_output_change_fraction,libfann),Void,(Ptr{fann},Cfloat),ann,cascade_output_change_fraction)
end

function fann_get_cascade_output_stagnation_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_output_stagnation_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_output_stagnation_epochs(ann::Ptr{fann},cascade_output_stagnation_epochs::Uint32)
    ccall((:fann_set_cascade_output_stagnation_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_output_stagnation_epochs)
end

function fann_get_cascade_candidate_change_fraction(ann::Ptr{fann})
    ccall((:fann_get_cascade_candidate_change_fraction,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_cascade_candidate_change_fraction(ann::Ptr{fann},cascade_candidate_change_fraction::Cfloat)
    ccall((:fann_set_cascade_candidate_change_fraction,libfann),Void,(Ptr{fann},Cfloat),ann,cascade_candidate_change_fraction)
end

function fann_get_cascade_candidate_stagnation_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_candidate_stagnation_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_candidate_stagnation_epochs(ann::Ptr{fann},cascade_candidate_stagnation_epochs::Uint32)
    ccall((:fann_set_cascade_candidate_stagnation_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_candidate_stagnation_epochs)
end

function fann_get_cascade_weight_multiplier(ann::Ptr{fann})
    ccall((:fann_get_cascade_weight_multiplier,libfann),fann_type,(Ptr{fann},),ann)
end

function fann_set_cascade_weight_multiplier(ann::Ptr{fann},cascade_weight_multiplier::fann_type)
    ccall((:fann_set_cascade_weight_multiplier,libfann),Void,(Ptr{fann},fann_type),ann,cascade_weight_multiplier)
end

function fann_get_cascade_candidate_limit(ann::Ptr{fann})
    ccall((:fann_get_cascade_candidate_limit,libfann),fann_type,(Ptr{fann},),ann)
end

function fann_set_cascade_candidate_limit(ann::Ptr{fann},cascade_candidate_limit::fann_type)
    ccall((:fann_set_cascade_candidate_limit,libfann),Void,(Ptr{fann},fann_type),ann,cascade_candidate_limit)
end

function fann_get_cascade_max_out_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_max_out_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_max_out_epochs(ann::Ptr{fann},cascade_max_out_epochs::Uint32)
    ccall((:fann_set_cascade_max_out_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_max_out_epochs)
end

function fann_get_cascade_min_out_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_min_out_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_min_out_epochs(ann::Ptr{fann},cascade_min_out_epochs::Uint32)
    ccall((:fann_set_cascade_min_out_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_min_out_epochs)
end

function fann_get_cascade_max_cand_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_max_cand_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_max_cand_epochs(ann::Ptr{fann},cascade_max_cand_epochs::Uint32)
    ccall((:fann_set_cascade_max_cand_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_max_cand_epochs)
end

function fann_get_cascade_min_cand_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_min_cand_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_min_cand_epochs(ann::Ptr{fann},cascade_min_cand_epochs::Uint32)
    ccall((:fann_set_cascade_min_cand_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_min_cand_epochs)
end

function fann_get_cascade_num_candidates(ann::Ptr{fann})
    ccall((:fann_get_cascade_num_candidates,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_cascade_activation_functions_count(ann::Ptr{fann})
    ccall((:fann_get_cascade_activation_functions_count,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_cascade_activation_functions(ann::Ptr{fann})
    ccall((:fann_get_cascade_activation_functions,libfann),Ptr{fann_activationfunc_enum},(Ptr{fann},),ann)
end

function fann_set_cascade_activation_functions(ann::Ptr{fann},cascade_activation_functions::Ptr{fann_activationfunc_enum},cascade_activation_functions_count::Uint32)
    ccall((:fann_set_cascade_activation_functions,libfann),Void,(Ptr{fann},Ptr{fann_activationfunc_enum},Uint32),ann,cascade_activation_functions,cascade_activation_functions_count)
end

function fann_get_cascade_activation_steepnesses_count(ann::Ptr{fann})
    ccall((:fann_get_cascade_activation_steepnesses_count,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_cascade_activation_steepnesses(ann::Ptr{fann})
    ccall((:fann_get_cascade_activation_steepnesses,libfann),Ptr{fann_type},(Ptr{fann},),ann)
end

function fann_set_cascade_activation_steepnesses(ann::Ptr{fann},cascade_activation_steepnesses::Ptr{fann_type},cascade_activation_steepnesses_count::Uint32)
    ccall((:fann_set_cascade_activation_steepnesses,libfann),Void,(Ptr{fann},Ptr{fann_type},Uint32),ann,cascade_activation_steepnesses,cascade_activation_steepnesses_count)
end

function fann_get_cascade_num_candidate_groups(ann::Ptr{fann})
    ccall((:fann_get_cascade_num_candidate_groups,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_num_candidate_groups(ann::Ptr{fann},cascade_num_candidate_groups::Uint32)
    ccall((:fann_set_cascade_num_candidate_groups,libfann),Void,(Ptr{fann},Uint32),ann,cascade_num_candidate_groups)
end

function fann_create_from_file(configuration_file::Ptr{Uint8})
    ccall((:fann_create_from_file,libfann),Ptr{fann},(Ptr{Uint8},),configuration_file)
end

function fann_save(ann::Ptr{fann},configuration_file::Ptr{Uint8})
    ccall((:fann_save,libfann),Cint,(Ptr{fann},Ptr{Uint8}),ann,configuration_file)
end

function fann_save_to_fixed(ann::Ptr{fann},configuration_file::Ptr{Uint8})
    ccall((:fann_save_to_fixed,libfann),Cint,(Ptr{fann},Ptr{Uint8}),ann,configuration_file)
end

function fann_create_standard_array(num_layers::Uint32,layers::Ptr{Uint32})
    ccall((:fann_create_standard_array,libfann),Ptr{fann},(Uint32,Ptr{Uint32}),num_layers,layers)
end

function fann_create_sparse_array(connection_rate::Cfloat,num_layers::Uint32,layers::Ptr{Uint32})
    ccall((:fann_create_sparse_array,libfann),Ptr{fann},(Cfloat,Uint32,Ptr{Uint32}),connection_rate,num_layers,layers)
end

function fann_create_shortcut_array(num_layers::Uint32,layers::Ptr{Uint32})
    ccall((:fann_create_shortcut_array,libfann),Ptr{fann},(Uint32,Ptr{Uint32}),num_layers,layers)
end

function fann_destroy(ann::Ptr{fann})
    ccall((:fann_destroy,libfann),Void,(Ptr{fann},),ann)
end

function fann_copy(ann::Ptr{fann})
    ccall((:fann_copy,libfann),Ptr{fann},(Ptr{fann},),ann)
end

function fann_run(ann::Ptr{fann},input::Ptr{fann_type})
    ccall((:fann_run,libfann),Ptr{fann_type},(Ptr{fann},Ptr{fann_type}),ann,input)
end

function fann_randomize_weights(ann::Ptr{fann},min_weight::fann_type,max_weight::fann_type)
    ccall((:fann_randomize_weights,libfann),Void,(Ptr{fann},fann_type,fann_type),ann,min_weight,max_weight)
end

function fann_init_weights(ann::Ptr{fann},train_data::Ptr{fann_train_data})
    ccall((:fann_init_weights,libfann),Void,(Ptr{fann},Ptr{fann_train_data}),ann,train_data)
end

function fann_print_connections(ann::Ptr{fann})
    ccall((:fann_print_connections,libfann),Void,(Ptr{fann},),ann)
end

function fann_print_parameters(ann::Ptr{fann})
    ccall((:fann_print_parameters,libfann),Void,(Ptr{fann},),ann)
end

function fann_get_num_input(ann::Ptr{fann})
    ccall((:fann_get_num_input,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_num_output(ann::Ptr{fann})
    ccall((:fann_get_num_output,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_total_neurons(ann::Ptr{fann})
    ccall((:fann_get_total_neurons,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_total_connections(ann::Ptr{fann})
    ccall((:fann_get_total_connections,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_network_type(ann::Ptr{fann})
    ccall((:fann_get_network_type,libfann),Cint,(Ptr{fann},),ann)
end

function fann_get_connection_rate(ann::Ptr{fann})
    ccall((:fann_get_connection_rate,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_get_num_layers(ann::Ptr{fann})
    ccall((:fann_get_num_layers,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_layer_array(ann::Ptr{fann},layers::Ptr{Uint32})
    ccall((:fann_get_layer_array,libfann),Void,(Ptr{fann},Ptr{Uint32}),ann,layers)
end

function fann_get_bias_array(ann::Ptr{fann},bias::Ptr{Uint32})
    ccall((:fann_get_bias_array,libfann),Void,(Ptr{fann},Ptr{Uint32}),ann,bias)
end

function fann_get_connection_array(ann::Ptr{fann},connections::Ptr{fann_connection})
    ccall((:fann_get_connection_array,libfann),Void,(Ptr{fann},Ptr{fann_connection}),ann,connections)
end

function fann_set_weight_array(ann::Ptr{fann},connections::Ptr{fann_connection},num_connections::Uint32)
    ccall((:fann_set_weight_array,libfann),Void,(Ptr{fann},Ptr{fann_connection},Uint32),ann,connections,num_connections)
end

function fann_set_weight(ann::Ptr{fann},from_neuron::Uint32,to_neuron::Uint32,weight::fann_type)
    ccall((:fann_set_weight,libfann),Void,(Ptr{fann},Uint32,Uint32,fann_type),ann,from_neuron,to_neuron,weight)
end

function fann_set_user_data(ann::Ptr{fann},user_data::Ptr{Void})
    ccall((:fann_set_user_data,libfann),Void,(Ptr{fann},Ptr{Void}),ann,user_data)
end

function fann_get_user_data(ann::Ptr{fann})
    ccall((:fann_get_user_data,libfann),Ptr{Void},(Ptr{fann},),ann)
end
# Julia wrapper for header: ../deps/usr/include/fann_activation.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0

# Julia wrapper for header: ../deps/usr/include/fann_cascade.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0

# Julia wrapper for header: ../deps/usr/include/fann_data.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0

# Julia wrapper for header: ../deps/usr/include/fann_error.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0

# Julia wrapper for header: ../deps/usr/include/fann_internal.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0

function fann_allocate_structure(num_layers::Uint32)
    ccall((:fann_allocate_structure,libfann),Ptr{fann},(Uint32,),num_layers)
end

function fann_allocate_neurons(ann::Ptr{fann})
    ccall((:fann_allocate_neurons,libfann),Void,(Ptr{fann},),ann)
end

function fann_allocate_connections(ann::Ptr{fann})
    ccall((:fann_allocate_connections,libfann),Void,(Ptr{fann},),ann)
end

function fann_save_internal(ann::Ptr{fann},configuration_file::Ptr{Uint8},save_as_fixed::Uint32)
    ccall((:fann_save_internal,libfann),Cint,(Ptr{fann},Ptr{Uint8},Uint32),ann,configuration_file,save_as_fixed)
end

function fann_save_internal_fd(ann::Ptr{fann},conf::Ptr{FILE},configuration_file::Ptr{Uint8},save_as_fixed::Uint32)
    ccall((:fann_save_internal_fd,libfann),Cint,(Ptr{fann},Ptr{FILE},Ptr{Uint8},Uint32),ann,conf,configuration_file,save_as_fixed)
end

function fann_save_train_internal(data::Ptr{fann_train_data},filename::Ptr{Uint8},save_as_fixed::Uint32,decimal_point::Uint32)
    ccall((:fann_save_train_internal,libfann),Cint,(Ptr{fann_train_data},Ptr{Uint8},Uint32,Uint32),data,filename,save_as_fixed,decimal_point)
end

function fann_save_train_internal_fd(data::Ptr{fann_train_data},file::Ptr{FILE},filename::Ptr{Uint8},save_as_fixed::Uint32,decimal_point::Uint32)
    ccall((:fann_save_train_internal_fd,libfann),Cint,(Ptr{fann_train_data},Ptr{FILE},Ptr{Uint8},Uint32,Uint32),data,file,filename,save_as_fixed,decimal_point)
end

function fann_update_stepwise(ann::Ptr{fann})
    ccall((:fann_update_stepwise,libfann),Void,(Ptr{fann},),ann)
end

function fann_init_error_data(errdat::Ptr{fann_error})
    ccall((:fann_init_error_data,libfann),Void,(Ptr{fann_error},),errdat)
end

function fann_create_from_fd(conf::Ptr{FILE},configuration_file::Ptr{Uint8})
    ccall((:fann_create_from_fd,libfann),Ptr{fann},(Ptr{FILE},Ptr{Uint8}),conf,configuration_file)
end

function fann_read_train_from_fd(file::Ptr{FILE},filename::Ptr{Uint8})
    ccall((:fann_read_train_from_fd,libfann),Ptr{fann_train_data},(Ptr{FILE},Ptr{Uint8}),file,filename)
end

function fann_compute_MSE(ann::Ptr{fann},desired_output::Ptr{Cint})
    ccall((:fann_compute_MSE,libfann),Void,(Ptr{fann},Ptr{Cint}),ann,desired_output)
end

function fann_update_output_weights(ann::Ptr{fann})
    ccall((:fann_update_output_weights,libfann),Void,(Ptr{fann},),ann)
end

function fann_backpropagate_MSE(ann::Ptr{fann})
    ccall((:fann_backpropagate_MSE,libfann),Void,(Ptr{fann},),ann)
end

function fann_update_weights(ann::Ptr{fann})
    ccall((:fann_update_weights,libfann),Void,(Ptr{fann},),ann)
end

function fann_update_slopes_batch(ann::Ptr{fann},layer_begin::Ptr{fann_layer},layer_end::Ptr{fann_layer})
    ccall((:fann_update_slopes_batch,libfann),Void,(Ptr{fann},Ptr{fann_layer},Ptr{fann_layer}),ann,layer_begin,layer_end)
end

function fann_update_weights_quickprop(ann::Ptr{fann},num_data::Uint32,first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_quickprop,libfann),Void,(Ptr{fann},Uint32,Uint32,Uint32),ann,num_data,first_weight,past_end)
end

function fann_update_weights_batch(ann::Ptr{fann},num_data::Uint32,first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_batch,libfann),Void,(Ptr{fann},Uint32,Uint32,Uint32),ann,num_data,first_weight,past_end)
end

function fann_update_weights_irpropm(ann::Ptr{fann},first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_irpropm,libfann),Void,(Ptr{fann},Uint32,Uint32),ann,first_weight,past_end)
end

function fann_update_weights_sarprop(ann::Ptr{fann},epoch::Uint32,first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_sarprop,libfann),Void,(Ptr{fann},Uint32,Uint32,Uint32),ann,epoch,first_weight,past_end)
end

function fann_clear_train_arrays(ann::Ptr{fann})
    ccall((:fann_clear_train_arrays,libfann),Void,(Ptr{fann},),ann)
end

function fann_activation()
    ccall((:fann_activation,libfann),Cint,())
end

function fann_activation_derived()
    ccall((:fann_activation_derived,libfann),Cint,())
end

function fann_desired_error_reached(ann::Ptr{fann},desired_error::Cfloat)
    ccall((:fann_desired_error_reached,libfann),Cint,(Ptr{fann},Cfloat),ann,desired_error)
end

function fann_train_outputs(ann::Ptr{fann},data::Ptr{fann_train_data},desired_error::Cfloat)
    ccall((:fann_train_outputs,libfann),Cint,(Ptr{fann},Ptr{fann_train_data},Cfloat),ann,data,desired_error)
end

function fann_train_outputs_epoch(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_train_outputs_epoch,libfann),Cfloat,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_train_candidates(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_train_candidates,libfann),Cint,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_train_candidates_epoch()
    ccall((:fann_train_candidates_epoch,libfann),Cint,())
end

function fann_install_candidate(ann::Ptr{fann})
    ccall((:fann_install_candidate,libfann),Void,(Ptr{fann},),ann)
end

function fann_check_input_output_sizes(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_check_input_output_sizes,libfann),Cint,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_initialize_candidates(ann::Ptr{fann})
    ccall((:fann_initialize_candidates,libfann),Cint,(Ptr{fann},),ann)
end

function fann_set_shortcut_connections(ann::Ptr{fann})
    ccall((:fann_set_shortcut_connections,libfann),Void,(Ptr{fann},),ann)
end

function fann_allocate_scale(ann::Ptr{fann})
    ccall((:fann_allocate_scale,libfann),Cint,(Ptr{fann},),ann)
end
# Julia wrapper for header: ../deps/usr/include/fann_io.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0

# Julia wrapper for header: ../deps/usr/include/fann_train.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0

# Julia wrapper for header: ../deps/usr/include/doublefann.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0

function fann_set_error_log(errdat::Ptr{fann_error},log_file::Ptr{FILE})
    ccall((:fann_set_error_log,libfann),Void,(Ptr{fann_error},Ptr{FILE}),errdat,log_file)
end

function fann_get_errno(errdat::Ptr{fann_error})
    ccall((:fann_get_errno,libfann),Cint,(Ptr{fann_error},),errdat)
end

function fann_reset_errno(errdat::Ptr{fann_error})
    ccall((:fann_reset_errno,libfann),Void,(Ptr{fann_error},),errdat)
end

function fann_reset_errstr(errdat::Ptr{fann_error})
    ccall((:fann_reset_errstr,libfann),Void,(Ptr{fann_error},),errdat)
end

function fann_get_errstr(errdat::Ptr{fann_error})
    ccall((:fann_get_errstr,libfann),Ptr{Uint8},(Ptr{fann_error},),errdat)
end

function fann_print_error(errdat::Ptr{fann_error})
    ccall((:fann_print_error,libfann),Void,(Ptr{fann_error},),errdat)
end

function fann_allocate_structure(num_layers::Uint32)
    ccall((:fann_allocate_structure,libfann),Ptr{fann},(Uint32,),num_layers)
end

function fann_allocate_neurons(ann::Ptr{fann})
    ccall((:fann_allocate_neurons,libfann),Void,(Ptr{fann},),ann)
end

function fann_allocate_connections(ann::Ptr{fann})
    ccall((:fann_allocate_connections,libfann),Void,(Ptr{fann},),ann)
end

function fann_save_internal(ann::Ptr{fann},configuration_file::Ptr{Uint8},save_as_fixed::Uint32)
    ccall((:fann_save_internal,libfann),Cint,(Ptr{fann},Ptr{Uint8},Uint32),ann,configuration_file,save_as_fixed)
end

function fann_save_internal_fd(ann::Ptr{fann},conf::Ptr{FILE},configuration_file::Ptr{Uint8},save_as_fixed::Uint32)
    ccall((:fann_save_internal_fd,libfann),Cint,(Ptr{fann},Ptr{FILE},Ptr{Uint8},Uint32),ann,conf,configuration_file,save_as_fixed)
end

function fann_save_train_internal(data::Ptr{fann_train_data},filename::Ptr{Uint8},save_as_fixed::Uint32,decimal_point::Uint32)
    ccall((:fann_save_train_internal,libfann),Cint,(Ptr{fann_train_data},Ptr{Uint8},Uint32,Uint32),data,filename,save_as_fixed,decimal_point)
end

function fann_save_train_internal_fd(data::Ptr{fann_train_data},file::Ptr{FILE},filename::Ptr{Uint8},save_as_fixed::Uint32,decimal_point::Uint32)
    ccall((:fann_save_train_internal_fd,libfann),Cint,(Ptr{fann_train_data},Ptr{FILE},Ptr{Uint8},Uint32,Uint32),data,file,filename,save_as_fixed,decimal_point)
end

function fann_update_stepwise(ann::Ptr{fann})
    ccall((:fann_update_stepwise,libfann),Void,(Ptr{fann},),ann)
end

function fann_init_error_data(errdat::Ptr{fann_error})
    ccall((:fann_init_error_data,libfann),Void,(Ptr{fann_error},),errdat)
end

function fann_create_from_fd(conf::Ptr{FILE},configuration_file::Ptr{Uint8})
    ccall((:fann_create_from_fd,libfann),Ptr{fann},(Ptr{FILE},Ptr{Uint8}),conf,configuration_file)
end

function fann_read_train_from_fd(file::Ptr{FILE},filename::Ptr{Uint8})
    ccall((:fann_read_train_from_fd,libfann),Ptr{fann_train_data},(Ptr{FILE},Ptr{Uint8}),file,filename)
end

function fann_compute_MSE(ann::Ptr{fann},desired_output::Ptr{fann_type})
    ccall((:fann_compute_MSE,libfann),Void,(Ptr{fann},Ptr{fann_type}),ann,desired_output)
end

function fann_update_output_weights(ann::Ptr{fann})
    ccall((:fann_update_output_weights,libfann),Void,(Ptr{fann},),ann)
end

function fann_backpropagate_MSE(ann::Ptr{fann})
    ccall((:fann_backpropagate_MSE,libfann),Void,(Ptr{fann},),ann)
end

function fann_update_weights(ann::Ptr{fann})
    ccall((:fann_update_weights,libfann),Void,(Ptr{fann},),ann)
end

function fann_update_slopes_batch(ann::Ptr{fann},layer_begin::Ptr{fann_layer},layer_end::Ptr{fann_layer})
    ccall((:fann_update_slopes_batch,libfann),Void,(Ptr{fann},Ptr{fann_layer},Ptr{fann_layer}),ann,layer_begin,layer_end)
end

function fann_update_weights_quickprop(ann::Ptr{fann},num_data::Uint32,first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_quickprop,libfann),Void,(Ptr{fann},Uint32,Uint32,Uint32),ann,num_data,first_weight,past_end)
end

function fann_update_weights_batch(ann::Ptr{fann},num_data::Uint32,first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_batch,libfann),Void,(Ptr{fann},Uint32,Uint32,Uint32),ann,num_data,first_weight,past_end)
end

function fann_update_weights_irpropm(ann::Ptr{fann},first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_irpropm,libfann),Void,(Ptr{fann},Uint32,Uint32),ann,first_weight,past_end)
end

function fann_update_weights_sarprop(ann::Ptr{fann},epoch::Uint32,first_weight::Uint32,past_end::Uint32)
    ccall((:fann_update_weights_sarprop,libfann),Void,(Ptr{fann},Uint32,Uint32,Uint32),ann,epoch,first_weight,past_end)
end

function fann_clear_train_arrays(ann::Ptr{fann})
    ccall((:fann_clear_train_arrays,libfann),Void,(Ptr{fann},),ann)
end

function fann_activation(ann::Ptr{fann},activation_function::Uint32,steepness::fann_type,value::fann_type)
    ccall((:fann_activation,libfann),fann_type,(Ptr{fann},Uint32,fann_type,fann_type),ann,activation_function,steepness,value)
end

function fann_activation_derived(activation_function::Uint32,steepness::fann_type,value::fann_type,sum::fann_type)
    ccall((:fann_activation_derived,libfann),fann_type,(Uint32,fann_type,fann_type,fann_type),activation_function,steepness,value,sum)
end

function fann_desired_error_reached(ann::Ptr{fann},desired_error::Cfloat)
    ccall((:fann_desired_error_reached,libfann),Cint,(Ptr{fann},Cfloat),ann,desired_error)
end

function fann_train_outputs(ann::Ptr{fann},data::Ptr{fann_train_data},desired_error::Cfloat)
    ccall((:fann_train_outputs,libfann),Cint,(Ptr{fann},Ptr{fann_train_data},Cfloat),ann,data,desired_error)
end

function fann_train_outputs_epoch(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_train_outputs_epoch,libfann),Cfloat,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_train_candidates(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_train_candidates,libfann),Cint,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_train_candidates_epoch(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_train_candidates_epoch,libfann),fann_type,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_install_candidate(ann::Ptr{fann})
    ccall((:fann_install_candidate,libfann),Void,(Ptr{fann},),ann)
end

function fann_check_input_output_sizes(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_check_input_output_sizes,libfann),Cint,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_initialize_candidates(ann::Ptr{fann})
    ccall((:fann_initialize_candidates,libfann),Cint,(Ptr{fann},),ann)
end

function fann_set_shortcut_connections(ann::Ptr{fann})
    ccall((:fann_set_shortcut_connections,libfann),Void,(Ptr{fann},),ann)
end

function fann_allocate_scale(ann::Ptr{fann})
    ccall((:fann_allocate_scale,libfann),Cint,(Ptr{fann},),ann)
end

function fann_scale_data_to_range(data::Ptr{Ptr{fann_type}},num_data::Uint32,num_elem::Uint32,old_min::fann_type,old_max::fann_type,new_min::fann_type,new_max::fann_type)
    ccall((:fann_scale_data_to_range,libfann),Void,(Ptr{Ptr{fann_type}},Uint32,Uint32,fann_type,fann_type,fann_type,fann_type),data,num_data,num_elem,old_min,old_max,new_min,new_max)
end

function fann_train(ann::Ptr{fann},input::Ptr{fann_type},desired_output::Ptr{fann_type})
    ccall((:fann_train,libfann),Void,(Ptr{fann},Ptr{fann_type},Ptr{fann_type}),ann,input,desired_output)
end

function fann_test(ann::Ptr{fann},input::Ptr{fann_type},desired_output::Ptr{fann_type})
    ccall((:fann_test,libfann),Ptr{fann_type},(Ptr{fann},Ptr{fann_type},Ptr{fann_type}),ann,input,desired_output)
end

function fann_get_MSE(ann::Ptr{fann})
    ccall((:fann_get_MSE,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_get_bit_fail(ann::Ptr{fann})
    ccall((:fann_get_bit_fail,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_reset_MSE(ann::Ptr{fann})
    ccall((:fann_reset_MSE,libfann),Void,(Ptr{fann},),ann)
end

function fann_train_on_data(ann::Ptr{fann},data::Ptr{fann_train_data},max_epochs::Uint32,epochs_between_reports::Uint32,desired_error::Cfloat)
    ccall((:fann_train_on_data,libfann),Void,(Ptr{fann},Ptr{fann_train_data},Uint32,Uint32,Cfloat),ann,data,max_epochs,epochs_between_reports,desired_error)
end

function fann_train_on_file(ann::Ptr{fann},filename::Ptr{Uint8},max_epochs::Uint32,epochs_between_reports::Uint32,desired_error::Cfloat)
    ccall((:fann_train_on_file,libfann),Void,(Ptr{fann},Ptr{Uint8},Uint32,Uint32,Cfloat),ann,filename,max_epochs,epochs_between_reports,desired_error)
end

function fann_train_epoch(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_train_epoch,libfann),Cfloat,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_test_data(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_test_data,libfann),Cfloat,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_read_train_from_file(filename::Ptr{Uint8})
    ccall((:fann_read_train_from_file,libfann),Ptr{fann_train_data},(Ptr{Uint8},),filename)
end

function fann_create_train(num_data::Uint32,num_input::Uint32,num_output::Uint32)
    ccall((:fann_create_train,libfann),Ptr{fann_train_data},(Uint32,Uint32,Uint32),num_data,num_input,num_output)
end

function fann_create_train_pointer_array(num_data::Uint32,num_input::Uint32,input::Ptr{Ptr{fann_type}},num_output::Uint32,output::Ptr{Ptr{fann_type}})
    ccall((:fann_create_train_pointer_array,libfann),Ptr{fann_train_data},(Uint32,Uint32,Ptr{Ptr{fann_type}},Uint32,Ptr{Ptr{fann_type}}),num_data,num_input,input,num_output,output)
end

function fann_create_train_array(num_data::Uint32,num_input::Uint32,input::Ptr{fann_type},num_output::Uint32,output::Ptr{fann_type})
    ccall((:fann_create_train_array,libfann),Ptr{fann_train_data},(Uint32,Uint32,Ptr{fann_type},Uint32,Ptr{fann_type}),num_data,num_input,input,num_output,output)
end

function fann_create_train_from_callback(num_data::Uint32,num_input::Uint32,num_output::Uint32,user_function::Ptr{Void})
    ccall((:fann_create_train_from_callback,libfann),Ptr{fann_train_data},(Uint32,Uint32,Uint32,Ptr{Void}),num_data,num_input,num_output,user_function)
end

function fann_destroy_train(train_data::Ptr{fann_train_data})
    ccall((:fann_destroy_train,libfann),Void,(Ptr{fann_train_data},),train_data)
end

function fann_get_train_input(data::Ptr{fann_train_data},position::Uint32)
    ccall((:fann_get_train_input,libfann),Ptr{fann_type},(Ptr{fann_train_data},Uint32),data,position)
end

function fann_get_train_output(data::Ptr{fann_train_data},position::Uint32)
    ccall((:fann_get_train_output,libfann),Ptr{fann_type},(Ptr{fann_train_data},Uint32),data,position)
end

function fann_shuffle_train_data(train_data::Ptr{fann_train_data})
    ccall((:fann_shuffle_train_data,libfann),Void,(Ptr{fann_train_data},),train_data)
end

function fann_scale_train(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_scale_train,libfann),Void,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_descale_train(ann::Ptr{fann},data::Ptr{fann_train_data})
    ccall((:fann_descale_train,libfann),Void,(Ptr{fann},Ptr{fann_train_data}),ann,data)
end

function fann_set_input_scaling_params(ann::Ptr{fann},data::Ptr{fann_train_data},new_input_min::Cfloat,new_input_max::Cfloat)
    ccall((:fann_set_input_scaling_params,libfann),Cint,(Ptr{fann},Ptr{fann_train_data},Cfloat,Cfloat),ann,data,new_input_min,new_input_max)
end

function fann_set_output_scaling_params(ann::Ptr{fann},data::Ptr{fann_train_data},new_output_min::Cfloat,new_output_max::Cfloat)
    ccall((:fann_set_output_scaling_params,libfann),Cint,(Ptr{fann},Ptr{fann_train_data},Cfloat,Cfloat),ann,data,new_output_min,new_output_max)
end

function fann_set_scaling_params(ann::Ptr{fann},data::Ptr{fann_train_data},new_input_min::Cfloat,new_input_max::Cfloat,new_output_min::Cfloat,new_output_max::Cfloat)
    ccall((:fann_set_scaling_params,libfann),Cint,(Ptr{fann},Ptr{fann_train_data},Cfloat,Cfloat,Cfloat,Cfloat),ann,data,new_input_min,new_input_max,new_output_min,new_output_max)
end

function fann_clear_scaling_params(ann::Ptr{fann})
    ccall((:fann_clear_scaling_params,libfann),Cint,(Ptr{fann},),ann)
end

function fann_scale_input(ann::Ptr{fann},input_vector::Ptr{fann_type})
    ccall((:fann_scale_input,libfann),Void,(Ptr{fann},Ptr{fann_type}),ann,input_vector)
end

function fann_scale_output(ann::Ptr{fann},output_vector::Ptr{fann_type})
    ccall((:fann_scale_output,libfann),Void,(Ptr{fann},Ptr{fann_type}),ann,output_vector)
end

function fann_descale_input(ann::Ptr{fann},input_vector::Ptr{fann_type})
    ccall((:fann_descale_input,libfann),Void,(Ptr{fann},Ptr{fann_type}),ann,input_vector)
end

function fann_descale_output(ann::Ptr{fann},output_vector::Ptr{fann_type})
    ccall((:fann_descale_output,libfann),Void,(Ptr{fann},Ptr{fann_type}),ann,output_vector)
end

function fann_scale_input_train_data(train_data::Ptr{fann_train_data},new_min::fann_type,new_max::fann_type)
    ccall((:fann_scale_input_train_data,libfann),Void,(Ptr{fann_train_data},fann_type,fann_type),train_data,new_min,new_max)
end

function fann_scale_output_train_data(train_data::Ptr{fann_train_data},new_min::fann_type,new_max::fann_type)
    ccall((:fann_scale_output_train_data,libfann),Void,(Ptr{fann_train_data},fann_type,fann_type),train_data,new_min,new_max)
end

function fann_scale_train_data(train_data::Ptr{fann_train_data},new_min::fann_type,new_max::fann_type)
    ccall((:fann_scale_train_data,libfann),Void,(Ptr{fann_train_data},fann_type,fann_type),train_data,new_min,new_max)
end

function fann_merge_train_data(data1::Ptr{fann_train_data},data2::Ptr{fann_train_data})
    ccall((:fann_merge_train_data,libfann),Ptr{fann_train_data},(Ptr{fann_train_data},Ptr{fann_train_data}),data1,data2)
end

function fann_duplicate_train_data(data::Ptr{fann_train_data})
    ccall((:fann_duplicate_train_data,libfann),Ptr{fann_train_data},(Ptr{fann_train_data},),data)
end

function fann_subset_train_data(data::Ptr{fann_train_data},pos::Uint32,length::Uint32)
    ccall((:fann_subset_train_data,libfann),Ptr{fann_train_data},(Ptr{fann_train_data},Uint32,Uint32),data,pos,length)
end

function fann_length_train_data(data::Ptr{fann_train_data})
    ccall((:fann_length_train_data,libfann),Uint32,(Ptr{fann_train_data},),data)
end

function fann_num_input_train_data(data::Ptr{fann_train_data})
    ccall((:fann_num_input_train_data,libfann),Uint32,(Ptr{fann_train_data},),data)
end

function fann_num_output_train_data(data::Ptr{fann_train_data})
    ccall((:fann_num_output_train_data,libfann),Uint32,(Ptr{fann_train_data},),data)
end

function fann_save_train(data::Ptr{fann_train_data},filename::Ptr{Uint8})
    ccall((:fann_save_train,libfann),Cint,(Ptr{fann_train_data},Ptr{Uint8}),data,filename)
end

function fann_save_train_to_fixed(data::Ptr{fann_train_data},filename::Ptr{Uint8},decimal_point::Uint32)
    ccall((:fann_save_train_to_fixed,libfann),Cint,(Ptr{fann_train_data},Ptr{Uint8},Uint32),data,filename,decimal_point)
end

function fann_get_training_algorithm(ann::Ptr{fann})
    ccall((:fann_get_training_algorithm,libfann),Cint,(Ptr{fann},),ann)
end

function fann_set_training_algorithm(ann::Ptr{fann},training_algorithm::fann_train_enum)
    ccall((:fann_set_training_algorithm,libfann),Void,(Ptr{fann},fann_train_enum),ann,training_algorithm)
end

function fann_get_learning_rate(ann::Ptr{fann})
    ccall((:fann_get_learning_rate,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_learning_rate(ann::Ptr{fann},learning_rate::Cfloat)
    ccall((:fann_set_learning_rate,libfann),Void,(Ptr{fann},Cfloat),ann,learning_rate)
end

function fann_get_learning_momentum(ann::Ptr{fann})
    ccall((:fann_get_learning_momentum,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_learning_momentum(ann::Ptr{fann},learning_momentum::Cfloat)
    ccall((:fann_set_learning_momentum,libfann),Void,(Ptr{fann},Cfloat),ann,learning_momentum)
end

function fann_get_activation_function(ann::Ptr{fann},layer::Cint,neuron::Cint)
    ccall((:fann_get_activation_function,libfann),Cint,(Ptr{fann},Cint,Cint),ann,layer,neuron)
end

function fann_set_activation_function(ann::Ptr{fann},activation_function::fann_activationfunc_enum,layer::Cint,neuron::Cint)
    ccall((:fann_set_activation_function,libfann),Void,(Ptr{fann},fann_activationfunc_enum,Cint,Cint),ann,activation_function,layer,neuron)
end

function fann_set_activation_function_layer(ann::Ptr{fann},activation_function::fann_activationfunc_enum,layer::Cint)
    ccall((:fann_set_activation_function_layer,libfann),Void,(Ptr{fann},fann_activationfunc_enum,Cint),ann,activation_function,layer)
end

function fann_set_activation_function_hidden(ann::Ptr{fann},activation_function::fann_activationfunc_enum)
    ccall((:fann_set_activation_function_hidden,libfann),Void,(Ptr{fann},fann_activationfunc_enum),ann,activation_function)
end

function fann_set_activation_function_output(ann::Ptr{fann},activation_function::fann_activationfunc_enum)
    ccall((:fann_set_activation_function_output,libfann),Void,(Ptr{fann},fann_activationfunc_enum),ann,activation_function)
end

function fann_get_activation_steepness(ann::Ptr{fann},layer::Cint,neuron::Cint)
    ccall((:fann_get_activation_steepness,libfann),fann_type,(Ptr{fann},Cint,Cint),ann,layer,neuron)
end

function fann_set_activation_steepness(ann::Ptr{fann},steepness::fann_type,layer::Cint,neuron::Cint)
    ccall((:fann_set_activation_steepness,libfann),Void,(Ptr{fann},fann_type,Cint,Cint),ann,steepness,layer,neuron)
end

function fann_set_activation_steepness_layer(ann::Ptr{fann},steepness::fann_type,layer::Cint)
    ccall((:fann_set_activation_steepness_layer,libfann),Void,(Ptr{fann},fann_type,Cint),ann,steepness,layer)
end

function fann_set_activation_steepness_hidden(ann::Ptr{fann},steepness::fann_type)
    ccall((:fann_set_activation_steepness_hidden,libfann),Void,(Ptr{fann},fann_type),ann,steepness)
end

function fann_set_activation_steepness_output(ann::Ptr{fann},steepness::fann_type)
    ccall((:fann_set_activation_steepness_output,libfann),Void,(Ptr{fann},fann_type),ann,steepness)
end

function fann_get_train_error_function(ann::Ptr{fann})
    ccall((:fann_get_train_error_function,libfann),Cint,(Ptr{fann},),ann)
end

function fann_set_train_error_function(ann::Ptr{fann},train_error_function::fann_errorfunc_enum)
    ccall((:fann_set_train_error_function,libfann),Void,(Ptr{fann},fann_errorfunc_enum),ann,train_error_function)
end

function fann_get_train_stop_function(ann::Ptr{fann})
    ccall((:fann_get_train_stop_function,libfann),Cint,(Ptr{fann},),ann)
end

function fann_set_train_stop_function(ann::Ptr{fann},train_stop_function::fann_stopfunc_enum)
    ccall((:fann_set_train_stop_function,libfann),Void,(Ptr{fann},fann_stopfunc_enum),ann,train_stop_function)
end

function fann_get_bit_fail_limit(ann::Ptr{fann})
    ccall((:fann_get_bit_fail_limit,libfann),fann_type,(Ptr{fann},),ann)
end

function fann_set_bit_fail_limit(ann::Ptr{fann},bit_fail_limit::fann_type)
    ccall((:fann_set_bit_fail_limit,libfann),Void,(Ptr{fann},fann_type),ann,bit_fail_limit)
end

function fann_set_callback(ann::Ptr{fann},callback::fann_callback_type)
    ccall((:fann_set_callback,libfann),Void,(Ptr{fann},fann_callback_type),ann,callback)
end

function fann_get_quickprop_decay(ann::Ptr{fann})
    ccall((:fann_get_quickprop_decay,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_quickprop_decay(ann::Ptr{fann},quickprop_decay::Cfloat)
    ccall((:fann_set_quickprop_decay,libfann),Void,(Ptr{fann},Cfloat),ann,quickprop_decay)
end

function fann_get_quickprop_mu(ann::Ptr{fann})
    ccall((:fann_get_quickprop_mu,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_quickprop_mu(ann::Ptr{fann},quickprop_mu::Cfloat)
    ccall((:fann_set_quickprop_mu,libfann),Void,(Ptr{fann},Cfloat),ann,quickprop_mu)
end

function fann_get_rprop_increase_factor(ann::Ptr{fann})
    ccall((:fann_get_rprop_increase_factor,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_rprop_increase_factor(ann::Ptr{fann},rprop_increase_factor::Cfloat)
    ccall((:fann_set_rprop_increase_factor,libfann),Void,(Ptr{fann},Cfloat),ann,rprop_increase_factor)
end

function fann_get_rprop_decrease_factor(ann::Ptr{fann})
    ccall((:fann_get_rprop_decrease_factor,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_rprop_decrease_factor(ann::Ptr{fann},rprop_decrease_factor::Cfloat)
    ccall((:fann_set_rprop_decrease_factor,libfann),Void,(Ptr{fann},Cfloat),ann,rprop_decrease_factor)
end

function fann_get_rprop_delta_min(ann::Ptr{fann})
    ccall((:fann_get_rprop_delta_min,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_rprop_delta_min(ann::Ptr{fann},rprop_delta_min::Cfloat)
    ccall((:fann_set_rprop_delta_min,libfann),Void,(Ptr{fann},Cfloat),ann,rprop_delta_min)
end

function fann_get_rprop_delta_max(ann::Ptr{fann})
    ccall((:fann_get_rprop_delta_max,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_rprop_delta_max(ann::Ptr{fann},rprop_delta_max::Cfloat)
    ccall((:fann_set_rprop_delta_max,libfann),Void,(Ptr{fann},Cfloat),ann,rprop_delta_max)
end

function fann_get_rprop_delta_zero(ann::Ptr{fann})
    ccall((:fann_get_rprop_delta_zero,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_rprop_delta_zero(ann::Ptr{fann},rprop_delta_max::Cfloat)
    ccall((:fann_set_rprop_delta_zero,libfann),Void,(Ptr{fann},Cfloat),ann,rprop_delta_max)
end

function fann_get_sarprop_weight_decay_shift(ann::Ptr{fann})
    ccall((:fann_get_sarprop_weight_decay_shift,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_sarprop_weight_decay_shift(ann::Ptr{fann},sarprop_weight_decay_shift::Cfloat)
    ccall((:fann_set_sarprop_weight_decay_shift,libfann),Void,(Ptr{fann},Cfloat),ann,sarprop_weight_decay_shift)
end

function fann_get_sarprop_step_error_threshold_factor(ann::Ptr{fann})
    ccall((:fann_get_sarprop_step_error_threshold_factor,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_sarprop_step_error_threshold_factor(ann::Ptr{fann},sarprop_step_error_threshold_factor::Cfloat)
    ccall((:fann_set_sarprop_step_error_threshold_factor,libfann),Void,(Ptr{fann},Cfloat),ann,sarprop_step_error_threshold_factor)
end

function fann_get_sarprop_step_error_shift(ann::Ptr{fann})
    ccall((:fann_get_sarprop_step_error_shift,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_sarprop_step_error_shift(ann::Ptr{fann},sarprop_step_error_shift::Cfloat)
    ccall((:fann_set_sarprop_step_error_shift,libfann),Void,(Ptr{fann},Cfloat),ann,sarprop_step_error_shift)
end

function fann_get_sarprop_temperature(ann::Ptr{fann})
    ccall((:fann_get_sarprop_temperature,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_sarprop_temperature(ann::Ptr{fann},sarprop_temperature::Cfloat)
    ccall((:fann_set_sarprop_temperature,libfann),Void,(Ptr{fann},Cfloat),ann,sarprop_temperature)
end

function fann_cascadetrain_on_data(ann::Ptr{fann},data::Ptr{fann_train_data},max_neurons::Uint32,neurons_between_reports::Uint32,desired_error::Cfloat)
    ccall((:fann_cascadetrain_on_data,libfann),Void,(Ptr{fann},Ptr{fann_train_data},Uint32,Uint32,Cfloat),ann,data,max_neurons,neurons_between_reports,desired_error)
end

function fann_cascadetrain_on_file(ann::Ptr{fann},filename::Ptr{Uint8},max_neurons::Uint32,neurons_between_reports::Uint32,desired_error::Cfloat)
    ccall((:fann_cascadetrain_on_file,libfann),Void,(Ptr{fann},Ptr{Uint8},Uint32,Uint32,Cfloat),ann,filename,max_neurons,neurons_between_reports,desired_error)
end

function fann_get_cascade_output_change_fraction(ann::Ptr{fann})
    ccall((:fann_get_cascade_output_change_fraction,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_cascade_output_change_fraction(ann::Ptr{fann},cascade_output_change_fraction::Cfloat)
    ccall((:fann_set_cascade_output_change_fraction,libfann),Void,(Ptr{fann},Cfloat),ann,cascade_output_change_fraction)
end

function fann_get_cascade_output_stagnation_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_output_stagnation_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_output_stagnation_epochs(ann::Ptr{fann},cascade_output_stagnation_epochs::Uint32)
    ccall((:fann_set_cascade_output_stagnation_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_output_stagnation_epochs)
end

function fann_get_cascade_candidate_change_fraction(ann::Ptr{fann})
    ccall((:fann_get_cascade_candidate_change_fraction,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_set_cascade_candidate_change_fraction(ann::Ptr{fann},cascade_candidate_change_fraction::Cfloat)
    ccall((:fann_set_cascade_candidate_change_fraction,libfann),Void,(Ptr{fann},Cfloat),ann,cascade_candidate_change_fraction)
end

function fann_get_cascade_candidate_stagnation_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_candidate_stagnation_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_candidate_stagnation_epochs(ann::Ptr{fann},cascade_candidate_stagnation_epochs::Uint32)
    ccall((:fann_set_cascade_candidate_stagnation_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_candidate_stagnation_epochs)
end

function fann_get_cascade_weight_multiplier(ann::Ptr{fann})
    ccall((:fann_get_cascade_weight_multiplier,libfann),fann_type,(Ptr{fann},),ann)
end

function fann_set_cascade_weight_multiplier(ann::Ptr{fann},cascade_weight_multiplier::fann_type)
    ccall((:fann_set_cascade_weight_multiplier,libfann),Void,(Ptr{fann},fann_type),ann,cascade_weight_multiplier)
end

function fann_get_cascade_candidate_limit(ann::Ptr{fann})
    ccall((:fann_get_cascade_candidate_limit,libfann),fann_type,(Ptr{fann},),ann)
end

function fann_set_cascade_candidate_limit(ann::Ptr{fann},cascade_candidate_limit::fann_type)
    ccall((:fann_set_cascade_candidate_limit,libfann),Void,(Ptr{fann},fann_type),ann,cascade_candidate_limit)
end

function fann_get_cascade_max_out_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_max_out_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_max_out_epochs(ann::Ptr{fann},cascade_max_out_epochs::Uint32)
    ccall((:fann_set_cascade_max_out_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_max_out_epochs)
end

function fann_get_cascade_min_out_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_min_out_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_min_out_epochs(ann::Ptr{fann},cascade_min_out_epochs::Uint32)
    ccall((:fann_set_cascade_min_out_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_min_out_epochs)
end

function fann_get_cascade_max_cand_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_max_cand_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_max_cand_epochs(ann::Ptr{fann},cascade_max_cand_epochs::Uint32)
    ccall((:fann_set_cascade_max_cand_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_max_cand_epochs)
end

function fann_get_cascade_min_cand_epochs(ann::Ptr{fann})
    ccall((:fann_get_cascade_min_cand_epochs,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_min_cand_epochs(ann::Ptr{fann},cascade_min_cand_epochs::Uint32)
    ccall((:fann_set_cascade_min_cand_epochs,libfann),Void,(Ptr{fann},Uint32),ann,cascade_min_cand_epochs)
end

function fann_get_cascade_num_candidates(ann::Ptr{fann})
    ccall((:fann_get_cascade_num_candidates,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_cascade_activation_functions_count(ann::Ptr{fann})
    ccall((:fann_get_cascade_activation_functions_count,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_cascade_activation_functions(ann::Ptr{fann})
    ccall((:fann_get_cascade_activation_functions,libfann),Ptr{fann_activationfunc_enum},(Ptr{fann},),ann)
end

function fann_set_cascade_activation_functions(ann::Ptr{fann},cascade_activation_functions::Ptr{fann_activationfunc_enum},cascade_activation_functions_count::Uint32)
    ccall((:fann_set_cascade_activation_functions,libfann),Void,(Ptr{fann},Ptr{fann_activationfunc_enum},Uint32),ann,cascade_activation_functions,cascade_activation_functions_count)
end

function fann_get_cascade_activation_steepnesses_count(ann::Ptr{fann})
    ccall((:fann_get_cascade_activation_steepnesses_count,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_cascade_activation_steepnesses(ann::Ptr{fann})
    ccall((:fann_get_cascade_activation_steepnesses,libfann),Ptr{fann_type},(Ptr{fann},),ann)
end

function fann_set_cascade_activation_steepnesses(ann::Ptr{fann},cascade_activation_steepnesses::Ptr{fann_type},cascade_activation_steepnesses_count::Uint32)
    ccall((:fann_set_cascade_activation_steepnesses,libfann),Void,(Ptr{fann},Ptr{fann_type},Uint32),ann,cascade_activation_steepnesses,cascade_activation_steepnesses_count)
end

function fann_get_cascade_num_candidate_groups(ann::Ptr{fann})
    ccall((:fann_get_cascade_num_candidate_groups,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_set_cascade_num_candidate_groups(ann::Ptr{fann},cascade_num_candidate_groups::Uint32)
    ccall((:fann_set_cascade_num_candidate_groups,libfann),Void,(Ptr{fann},Uint32),ann,cascade_num_candidate_groups)
end

function fann_create_from_file(configuration_file::Ptr{Uint8})
    ccall((:fann_create_from_file,libfann),Ptr{fann},(Ptr{Uint8},),configuration_file)
end

function fann_save(ann::Ptr{fann},configuration_file::Ptr{Uint8})
    ccall((:fann_save,libfann),Cint,(Ptr{fann},Ptr{Uint8}),ann,configuration_file)
end

function fann_save_to_fixed(ann::Ptr{fann},configuration_file::Ptr{Uint8})
    ccall((:fann_save_to_fixed,libfann),Cint,(Ptr{fann},Ptr{Uint8}),ann,configuration_file)
end

function fann_create_standard_array(num_layers::Uint32,layers::Ptr{Uint32})
    ccall((:fann_create_standard_array,libfann),Ptr{fann},(Uint32,Ptr{Uint32}),num_layers,layers)
end

function fann_create_sparse_array(connection_rate::Cfloat,num_layers::Uint32,layers::Ptr{Uint32})
    ccall((:fann_create_sparse_array,libfann),Ptr{fann},(Cfloat,Uint32,Ptr{Uint32}),connection_rate,num_layers,layers)
end

function fann_create_shortcut_array(num_layers::Uint32,layers::Ptr{Uint32})
    ccall((:fann_create_shortcut_array,libfann),Ptr{fann},(Uint32,Ptr{Uint32}),num_layers,layers)
end

function fann_destroy(ann::Ptr{fann})
    ccall((:fann_destroy,libfann),Void,(Ptr{fann},),ann)
end

function fann_copy(ann::Ptr{fann})
    ccall((:fann_copy,libfann),Ptr{fann},(Ptr{fann},),ann)
end

function fann_run(ann::Ptr{fann},input::Ptr{fann_type})
    ccall((:fann_run,libfann),Ptr{fann_type},(Ptr{fann},Ptr{fann_type}),ann,input)
end

function fann_randomize_weights(ann::Ptr{fann},min_weight::fann_type,max_weight::fann_type)
    ccall((:fann_randomize_weights,libfann),Void,(Ptr{fann},fann_type,fann_type),ann,min_weight,max_weight)
end

function fann_init_weights(ann::Ptr{fann},train_data::Ptr{fann_train_data})
    ccall((:fann_init_weights,libfann),Void,(Ptr{fann},Ptr{fann_train_data}),ann,train_data)
end

function fann_print_connections(ann::Ptr{fann})
    ccall((:fann_print_connections,libfann),Void,(Ptr{fann},),ann)
end

function fann_print_parameters(ann::Ptr{fann})
    ccall((:fann_print_parameters,libfann),Void,(Ptr{fann},),ann)
end

function fann_get_num_input(ann::Ptr{fann})
    ccall((:fann_get_num_input,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_num_output(ann::Ptr{fann})
    ccall((:fann_get_num_output,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_total_neurons(ann::Ptr{fann})
    ccall((:fann_get_total_neurons,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_total_connections(ann::Ptr{fann})
    ccall((:fann_get_total_connections,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_network_type(ann::Ptr{fann})
    ccall((:fann_get_network_type,libfann),Cint,(Ptr{fann},),ann)
end

function fann_get_connection_rate(ann::Ptr{fann})
    ccall((:fann_get_connection_rate,libfann),Cfloat,(Ptr{fann},),ann)
end

function fann_get_num_layers(ann::Ptr{fann})
    ccall((:fann_get_num_layers,libfann),Uint32,(Ptr{fann},),ann)
end

function fann_get_layer_array(ann::Ptr{fann},layers::Ptr{Uint32})
    ccall((:fann_get_layer_array,libfann),Void,(Ptr{fann},Ptr{Uint32}),ann,layers)
end

function fann_get_bias_array(ann::Ptr{fann},bias::Ptr{Uint32})
    ccall((:fann_get_bias_array,libfann),Void,(Ptr{fann},Ptr{Uint32}),ann,bias)
end

function fann_get_connection_array(ann::Ptr{fann},connections::Ptr{fann_connection})
    ccall((:fann_get_connection_array,libfann),Void,(Ptr{fann},Ptr{fann_connection}),ann,connections)
end

function fann_set_weight_array(ann::Ptr{fann},connections::Ptr{fann_connection},num_connections::Uint32)
    ccall((:fann_set_weight_array,libfann),Void,(Ptr{fann},Ptr{fann_connection},Uint32),ann,connections,num_connections)
end

function fann_set_weight(ann::Ptr{fann},from_neuron::Uint32,to_neuron::Uint32,weight::fann_type)
    ccall((:fann_set_weight,libfann),Void,(Ptr{fann},Uint32,Uint32,fann_type),ann,from_neuron,to_neuron,weight)
end

function fann_set_user_data(ann::Ptr{fann},user_data::Ptr{Void})
    ccall((:fann_set_user_data,libfann),Void,(Ptr{fann},Ptr{Void}),ann,user_data)
end

function fann_get_user_data(ann::Ptr{fann})
    ccall((:fann_get_user_data,libfann),Ptr{Void},(Ptr{fann},),ann)
end
# Julia wrapper for header: ../deps/usr/include/fann_cpp.h
# Automatically generated using Clang.jl wrap_c, version 0.0.0


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

using Markdown
using InteractiveUtils

# ╔═╡ 32504772-aaef-11eb-0bb0-0b145c5102db
begin
	using Base.Threads
	using Random
	using Distributions
	using SpecialFunctions
	using Plots
	using StatsPlots
	using Query
	using DataFrames
	using CSV
end

# ╔═╡ ec00bfbc-4889-4fbc-9f5b-ce19b361f1fe
md"""
## Estimating π in Buffon's Needle Problem
First we estimate π many times by simulating Buffon's needle problem. This is repeated for a variety of experimental setups, varying the number of needles thrown (`n_throws`) and the needle length (`needle_length`). For simplicity, we'll just assume that the strip height (`strip_height`) is one - so you can think of the needle length as the ratio of the needle length to the strip height.
"""

# ╔═╡ 7e54380a-fada-40c0-ad20-5795075f2c41
function needle_crossing_fraction(strip_height, needle_length, n_throws)
	D = rand(Uniform(0, strip_height/2), n_throws)
	θ = rand(Uniform(0, π), n_throws)

	crosses_line = (needle_length / 2) * sin.(θ) .> D
	n_crossings = sum(crosses_line)

	return n_crossings / n_throws
end

# ╔═╡ 3de8036e-723b-4805-9384-f87a6aaae5ba
function buffon_pi_estimate(strip_height, needle_length, n_throws)
	p_hat = needle_crossing_fraction(strip_height, needle_length, n_throws)

	return 2 * (needle_length / strip_height) / p_hat
end

# ╔═╡ 9e97dbc2-7d87-40cd-92a8-e892e485d9e6
buffon_pi_estimate(1, 0.1, 10^7)

# ╔═╡ 7838810d-63c0-4de6-8ec7-97a4b65750e2
function estimate_pi_repeatedly(
		n_needle_lengths = 10,
		n_repetitions = 100,
		n_throws_max_exp = 6
	)

	# Set up experiment, arrange data so that (when multi-threading) the
	# processors will be running similar problems at similar times
	df = DataFrame(
		[(needle_length,  n_throws, repetition)
			for n_throws = [10^k for k = 2:n_throws_max_exp]
			for needle_length = [k/n_needle_lengths for k = 1:n_needle_lengths]
			for repetition = 1:n_repetitions]
	)
	rename!(df, ["needle_length", "n_throws", "repetition"])

	# Number of experiments to run
	n_experiments = nrow(df)

	# Run multi-threaded experiments to estimate π
	pi_estimates = zeros(n_experiments)

	Threads.@threads for i ∈ 1:n_experiments
		needle_length = df[i, :needle_length]
		n_throws = df[i, :n_throws]
		pi_estimates[i] = buffon_pi_estimate(1, needle_length, n_throws)
	end

	df.pi_estimate = pi_estimates

	# Evaluate error
	df.error = df.pi_estimate .- π
	df.abs_error = abs.(df.error)

	return df
end

# ╔═╡ bbd5cc5f-80f2-405f-aa71-da0022d74863
pi_estimate_results = estimate_pi_repeatedly(10, 1000, 6)

# ╔═╡ 62e8e764-516a-452a-8f7f-806bf696b126
CSV.write("pi_estimate_results.csv", pi_estimate_results)

# ╔═╡ 27eabc0d-b40f-448f-90ce-301871f3b63b
md"""
## Analyzing the Error in Estimating π
In this section, we take a look at the error committed in estimating π in the various experiments performed above. In particular, we take a look at how the error depends upon the number of needles thrown and how long our needles are. In particular, we take a look at the median error and 95ᵗʰ percentile of our experiments.

In addition, I have computed the theoretical error "bounds" (note this bound is only asymptotically correct / hence more of a guide than a hard and fast "bound"), for 50% and 95% confidence bounds. I didn't bother to plot the actual vs theoretical comparison however, since they're not hard and fast bounds.

I have (however) plotted the observed median and 95ᵗʰ percentile observed error across the experimental set-ups.
"""

# ╔═╡ 6c17402b-8905-463c-aa0f-3a4905877944
md"""

### Analytical Asymptotic Error Bound
Elsewhere, I computed that the following bound holds asymptotically with probability $$P = 1-\alpha$$ (here, $$\Phi^{-1}$$ denotes the probit function, $$h$$ the strip width, $$\ell$$ the needle length, and $$\hat{\pi}$$ the estimate from throwing needles):

$$\vert \hat{\pi} - \pi \vert \lessapprox \pi  \sqrt{\frac{\pi}{2} - \frac{\ell}{h}} \cdot \Phi^{-1}\left(1 - \frac{\alpha}{2}\right)\cdot \sqrt{\frac{h}{\ell}} \cdot \frac{1}{\sqrt{n_\text{throws}}}.$$

We will compare against this below.
"""

# ╔═╡ d75c194b-20df-4ea8-a415-7c44167271d4
function probit(p)
	sqrt(2) * erfinv(2*p - 1)
end

# ╔═╡ 60f54651-6926-4248-aa40-f135d01e4347
function error_bound(needle_length, strip_width, prob_in_interval, n_throws)
	return π * √(π/2 - (needle_length/ strip_width)) *
	                    probit(1 - prob_in_interval/2) *
		                √(strip_width / needle_length) *
	                    1/√(n_throws)
end

# ╔═╡ 3c1ade5a-7a15-4585-8cf2-48b6c84813f7
md"""
The following table shows empirical error bounds, compared against the theoretical approximate bounds.
"""

# ╔═╡ a3304dce-9e87-444d-ab5d-c0f3fffea134
begin
	pi_error_analysis = combine(
		groupby(pi_estimate_results, [:needle_length, :n_throws]),
		:abs_error => median,
		:abs_error => (t -> quantile(t, 0.95))
	)

	rename!(pi_error_analysis, "abs_error_function" => "abs_error_95_pctile")

	transform!(pi_error_analysis, :, [:needle_length, :n_throws] =>
                                     ((a,b) -> error_bound.(a, 1, 0.5, b)) =>
		                             :abs_error_median_theoretical)

	transform!(pi_error_analysis, :, [:needle_length, :n_throws] =>
                                     ((a,b) -> error_bound.(a, 1, 0.05, b)) =>
		                             :abs_error_95_pctile_theoretical)

	pi_error_analysis
end

# ╔═╡ 902e5796-6741-4c4a-9856-a43006c326ab
CSV.write("pi_error_analysis.csv", pi_error_analysis)

# ╔═╡ 7014ffed-1bed-41aa-95ef-ecdcd366b510
md"""
The following plot shows the empirical median absolute error, compared against the theoretical approximate 50% percent confident bound on error.
"""

# ╔═╡ ab93cbb3-6b82-48d7-8fdd-4c91f300d33c
begin
	plot_ref_50th = pi_error_analysis |>
	@df scatter(
		:n_throws,
		:abs_error_median,
		group=:needle_length,
		color=reshape(palette(:auto)[1:10], (1, 10)),
		label=reshape(["" for i =1:10], (1,10)),
		# ugly hack to hide junk entry:
		xaxis=((75, 10^6+5*10^5), :log),
		yaxis=:log
	)

	pi_error_analysis |>
	@df plot!(
		:n_throws,
		:abs_error_median_theoretical,
		group=:needle_length,
		#legend=false
		color=reshape(palette(:auto)[1:10], (1, 10)),
		ylabel="Median of Absolute Error",
		xlabel="Number of Needles Thrown",
		title="Median Absolute Error vs Number of Needles Thrown\nby Needle Length",
		titlefontsize=10,
		legendtitle="Needle Length",
		legendtitlefontsize=8,
		legend = :outertopright

	)

	# junk data to get legend entries
    plot!([], [], label = " ", color = "white")
    plot!([], [], label = "Theoretical", color = "black")
    scatter!([10], [1], label = "Observed", color="black")

	# save figure
	savefig(plot_ref_50th, "error_plot_50pctile.svg")

	# display result in Pluto
	plot_ref_50th
end

# ╔═╡ ed32a816-05d8-46f2-b3fe-6a9c5a2f2636
md"""
The following plot shows the empirical 95ᵗʰ percentile of absolute error, compared against the theoretical 95% confident bound on error.
"""

# ╔═╡ a5f76835-73ce-4fa9-a0b0-e63f1f8bff69
begin
	plot_ref_95th = pi_error_analysis |>
	@df scatter(
		:n_throws,
		:abs_error_95_pctile,
		group=:needle_length,
		color=reshape(palette(:auto)[1:10], (1, 10)),
		label=reshape(["" for i =1:10], (1,10)),
		# ugly hack to hide junk entry:
		xaxis=((75, 10^6+5*10^5), :log),
		yaxis=:log
	)

	pi_error_analysis |>
	@df plot!(
		:n_throws,
		:abs_error_95_pctile_theoretical,
		group=:needle_length,
		#legend=false
		color=reshape(palette(:auto)[1:10], (1, 10)),
		ylabel="95ᵗʰ Percentile of Absolute Error",
		xlabel="Number of Needles Thrown",
		title="95ᵗʰ Percentile of Absolute Error vs Number of Needles Thrown\nby Needle Length",
		titlefontsize=10,
		legendtitle="Needle Length",
		legendtitlefontsize=8,
		legend = :outertopright

	)

	# junk data to get legend entries
    plot!([], [], label = " ", color = "white")
    plot!([], [], label = "Theoretical", color = "black")
    scatter!([10], [1], label = "Observed", color="black")

	# save figure
	savefig(plot_ref_95th, "error_plot_95pctile.svg")

	# display result in Pluto
	plot_ref_95th
end

# ╔═╡ bde8330a-fb98-4950-ad92-c82e2e5e65c6
md"""
### Plotting π Estimates when `needle_length = 1.0`

Since we have a lot of estimates for π, but have only looked at the error we made when estimating them (as opposed to the estimates themselves), I figure I should at least take a look at the estimates in one of the experimental settings.
"""

# ╔═╡ d82dd81c-bf96-443e-8b5a-aa75b21e037e
begin
	df_tmp = filter(row -> row[:needle_length] == 1.0, pi_estimate_results)

	plot_ref_len_1 = df_tmp |>
	@df dotplot(
		string.(:n_throws),
		:pi_estimate,
		ylabel="Estimate for π",
		xlabel="Number of Needles Thrown",
		title="Distribution of π Estimates by Number of Needles Thrown\nFor Needle Length=1.0",
		titlefontsize=11,
		marker=(:lightgrey, stroke(0))
	)

	plot_ref_len_1 = df_tmp |>
	@df boxplot!(
		string.(:n_throws),
		:pi_estimate,
		marker=(:black, stroke(0)),
		fillcolor=:lightblue,
		fillalpha=0.75,
		legend=false
	)

	# save figure
	savefig(plot_ref_len_1, "pi_estimate_boxplot.svg")

	# show figure
	plot_ref_len_1
end

# ╔═╡ b29276d8-e541-4221-b81f-fde2600a8979
md"""
The following table summarizes the results:
"""

# ╔═╡ 312ba44a-dcad-4b18-b130-3439625f78f3
begin
	pi_rslt = combine(
		groupby(pi_estimate_results, [:needle_length, :n_throws]),
		:pi_estimate => mean => :mean,
		:pi_estimate => minimum => :min,
		:pi_estimate => (t -> quantile(t, 0.25)) => :pctile_25,
		:pi_estimate => median => :median,
		:pi_estimate => (t -> quantile(t, 0.75)) => :pctile_75,
		:pi_estimate => maximum => :max,
	)
end

# ╔═╡ b847e348-4afd-4e63-b91b-84152cbb89b7
md"""
Let's take a look at the `needle_length = 1` case.
"""

# ╔═╡ e2042def-bf39-4b95-bdc9-1d46db79c88e
# show an interesting subset
filter(row -> row[:needle_length] == 1.0, pi_rslt)

# ╔═╡ 9b3f7234-9978-43bb-9af9-55bdf967ed62
# save to file
CSV.write("pi_rslt.csv", pi_rslt)

# ╔═╡ 489c446d-f942-4703-b0d7-7a29c98ce4d5
md"""
## How Many Needles Do I Need to Throw?
Finally, I will use the theoretical 95ᵗʰ percentile error bound to estimate how many needles one needs to throw in order to achieve a specified decimal digit accuracy (with 95% confidence) in estimating π.
"""

# ╔═╡ aeb3c67c-5248-4312-9930-852259f43de9
function n_throws_required(desired_accuracy, needle_length, strip_width,
		                   prob_in_interval)

	p = 1 - prob_in_interval

	n_throws =  π^2 * (π/2 - (needle_length / strip_width)) *
	                  probit(1 - p/2)^2 *
		              (strip_width / needle_length) *
	                  (1 / desired_accuracy^2)

	return n_throws
end

# ╔═╡ b988a3e4-1d15-4abf-8b5a-fc8a2e119c7e
begin
	df_required_analytical = DataFrame([
	 (decimal_digits, needle_length, n_throws_required(1/10^decimal_digits,                                                                  needle_length, 1, 0.95))
			for decimal_digits = [1, 2, 3, 4, 5, 6]
			for needle_length = [k/10 for k = 1:10]
	])

	rename!(df_required_analytical, ["decimal_digits", "needle_length",                                                    "throws_required"])
end

# ╔═╡ 55234b47-1b22-4fab-a449-c43b2976b7fa
md"""
Let's take a look at the `needle_length = 1` case.
"""

# ╔═╡ 9668af8a-ecea-4c11-9c3a-f32b416f02a9
# show an interesting subset
filter(row -> row[:needle_length] == 1.0, df_required_analytical)

# ╔═╡ fd88ca22-a191-4e92-900f-c86c7f516641
CSV.write(
	"required_throws_analytical_solution.csv",
	df_required_analytical
)

# ╔═╡ 70b92add-4a58-4181-8409-c896b57665f9
begin
	plot_ref_throws_req = df_required_analytical |>
	@df plot(
		:decimal_digits,
		:throws_required,
		group=:needle_length,
		yaxis=:log,
		ylabel="Number of Throws Required",
		xlabel="Number of Decimal Digits",
		title="Number of Throws Required to Achieve Specified\nDecimal Digit Accuracy with 95% Confidence\nby Needle Length",
		titlefontsize=11,
		legendtitle="Needle Length",
		legendtitlefontsize=8,
		legend = :outertopright
	)

	# save figure
	savefig(plot_ref_throws_req, "throws_required_95pctile.svg")

	# display plot
	plot_ref_throws_req
end

# ╔═╡ Cell order:
# ╟─ec00bfbc-4889-4fbc-9f5b-ce19b361f1fe
# ╠═7e54380a-fada-40c0-ad20-5795075f2c41
# ╠═3de8036e-723b-4805-9384-f87a6aaae5ba
# ╠═9e97dbc2-7d87-40cd-92a8-e892e485d9e6
# ╠═7838810d-63c0-4de6-8ec7-97a4b65750e2
# ╠═bbd5cc5f-80f2-405f-aa71-da0022d74863
# ╠═62e8e764-516a-452a-8f7f-806bf696b126
# ╟─27eabc0d-b40f-448f-90ce-301871f3b63b
# ╟─6c17402b-8905-463c-aa0f-3a4905877944
# ╠═d75c194b-20df-4ea8-a415-7c44167271d4
# ╠═60f54651-6926-4248-aa40-f135d01e4347
# ╟─3c1ade5a-7a15-4585-8cf2-48b6c84813f7
# ╠═a3304dce-9e87-444d-ab5d-c0f3fffea134
# ╠═902e5796-6741-4c4a-9856-a43006c326ab
# ╟─7014ffed-1bed-41aa-95ef-ecdcd366b510
# ╠═ab93cbb3-6b82-48d7-8fdd-4c91f300d33c
# ╟─ed32a816-05d8-46f2-b3fe-6a9c5a2f2636
# ╠═a5f76835-73ce-4fa9-a0b0-e63f1f8bff69
# ╟─bde8330a-fb98-4950-ad92-c82e2e5e65c6
# ╠═d82dd81c-bf96-443e-8b5a-aa75b21e037e
# ╟─b29276d8-e541-4221-b81f-fde2600a8979
# ╠═312ba44a-dcad-4b18-b130-3439625f78f3
# ╟─b847e348-4afd-4e63-b91b-84152cbb89b7
# ╠═e2042def-bf39-4b95-bdc9-1d46db79c88e
# ╠═9b3f7234-9978-43bb-9af9-55bdf967ed62
# ╟─489c446d-f942-4703-b0d7-7a29c98ce4d5
# ╠═aeb3c67c-5248-4312-9930-852259f43de9
# ╠═b988a3e4-1d15-4abf-8b5a-fc8a2e119c7e
# ╟─55234b47-1b22-4fab-a449-c43b2976b7fa
# ╠═9668af8a-ecea-4c11-9c3a-f32b416f02a9
# ╠═fd88ca22-a191-4e92-900f-c86c7f516641
# ╠═70b92add-4a58-4181-8409-c896b57665f9
# ╠═32504772-aaef-11eb-0bb0-0b145c5102db

ext: jl


text:
"""
    Primal

This struct is used for dispatching which `element_routine!` is used when you add your own element routines.
`Primal` refers to the primal format of the moment equilibrium:
```math
- \\boldsymbol{\\sigma} \\cdot \\boldsymbol{\\nabla} = \\boldsymbol{0}
```

with boundary conditions on the boundary ``\\Gamma = \\Gamma_\\text{D} \\cup \\Gamma_\\text{N}``

```math
\\begin{aligned}
\\boldsymbol{u} &= \\boldsymbol{u}_\\text{p} \\quad \\text{on} \\quad \\Gamma_\\text{D} \\\\
\\boldsymbol{t} &= \\boldsymbol{t}_\\text{p} \\quad \\text{on} \\quad \\Gamma_\\text{N} \\\\
\\end{aligned}
```

where \$\\boldsymbol{u}\$ is the primary unknown field.
"""
struct Primal end

"""
    element_routine!(::Primal, ke, fe, cv, xe, material, thickness[, fv, grid, cellid, tₚ, faceset_name])

Compute the element stiffness matrix `ke` and the element external load vector `fe`:

```math
\\begin{aligned}

\\left( ke \\right)_{ij} &= a\\left( \\boldsymbol{N}^{(\\rm u)}_i, \\, \\boldsymbol{N}^{(\\rm u)}_j \\right)
= \\int_\\Omega \\boldsymbol{\\nabla}^\\text{sym} \\boldsymbol{N}^{(\\rm u)}_i : \\boldsymbol{\\mathsf{E}} :
\\boldsymbol{\\nabla}^\\text{sym} \\boldsymbol{N}^{(\\rm u)}_j \\rm d \\Omega \\\\

\\left( fe \\right)_{i} &= l\\left( \\boldsymbol{N}^{(\\rm u)}_i \\right)
= \\int_{\\Gamma^{(\\rm u)}_\\text{N} } \\boldsymbol{N}^{(\\rm u)}_i \\cdot \\boldsymbol{t}_\\text{p} \\, \\rm d \\Gamma

\\end{aligned}
```

# Arguments:
- `ke`: element stiffness matrix
- `fe`: element force vector
- `cv`: CellVectorValues
- `xe`: element coordinate vector
- `material`: material parameters, for instant only `LinearElasticity` is allowed
- `thickness`: out-of-plane thickness

# Optional arguments for integrating the load vector:
- `fv`: FaceVectorValues
- `grid`: Grid
- `cellid`: global cell index of the current cell
- `tₚ`: traction vector
- `faceset_name`: name of the faceset over which the load vector should be integrated
"""
function element_routine!(
    ::Primal,
    ke,
    fe,
    cv,
    xe,
    material,
    thickness,
    fv=nothing,
    grid = nothing,
    cellid = nothing,
    tₚ=nothing,
    faceset_name=nothing,
)
    fill!(ke, 0.0)
    fill!(fe, 0.0)

    # unpack variables
    E = material.Eᵉ

    reinit!(cv, xe)

    ndof = getnbasefunctions(cv)

    # assemble a(u, δu)
    for qp in 1:getnquadpoints(cv) # both cellvalues have the same number of qp
        detJ = getdetJdV(cv, qp)
        for j in 1:ndof
            ∇Nⱼᵘ_sym = shape_symmetric_gradient(cv, qp, j)
            for i in 1:ndof
                ∇Nᵢᵘ_sym = shape_symmetric_gradient(cv, qp, i)
                ke[i,j] += ∇Nᵢᵘ_sym ⊡ E ⊡ ∇Nⱼᵘ_sym * detJ * thickness
            end
        end
    end

    # assemble l(δu)
    if faceset_name !== nothing
        if cellid === nothing || grid === nothing || fv === nothing || tₚ === nothing
            error("You must give a cellid, grid, facevalues and a traction vector for integrating the load vector.")
        end
        for face in 1:nfaces(getcells(grid, cellid))
            if FaceIndex(cellid, face) ∈ getfaceset(grid, faceset_name)
                reinit!(fv, xe, face)
                for qp in 1:getnquadpoints(fv)
                    detJ = getdetJdV(fv, qp)
                    for i in 1:ndof
                        Nᵢᵘ = shape_value(fv, qp, i)
                        fe[i] += Nᵢᵘ ⋅ tₚ * detJ * thickness
                    end
                end
            end
        end
    end

    return ke, fe
end


text:
"""
    $(SIGNATURES)

Experience log-wage profiles, read from regression file.
Zero for first year of experience.

Most robust to simply store the profile (0 intercept) as a vector
by schooling.
"""
function exper_profile(ds :: DataSettings, s :: Symbol; T :: Integer = 60)
    wr = wage_regr_settings(ds);
    # @assert 1 ≤ s ≤ n_school(ds);
    @assert n_school(wr) == n_school(ds)

    bExpV = read_exper_coefficients(ds, s);

    outV = zeros(T);
    # Estimated on about 12 years of experience
    expMax = max_exper(wr);
    xV = 0 : (expMax - 1);
    for j = 1 : length(bExpV)
        outV[1 : expMax] .+= bExpV[j] .* (xV .^ j) ./ (10.0 ^ (j-1));
    end
    splice_rupert_zanella!(outV, expMax, s);
    # Assumed constant after `expMax` years of experience
    # outV[(expMax + 1) : end] .= outV[expMax];

    @assert outV[1] == 0.0
    @assert maximum(outV) < 1.2
    return outV :: Vector{Float64}
end

# Read experience coefficients from "dat" file
function read_exper_coefficients(ds :: DataSettings, s :: Symbol)
    # File name with regression coefficients for this case
    rf = exper_raw_file(ds, s);
    rt = read_regression_file(rf);

    wr = wage_regr_settings(ds);
    nx = max_exper_exponent(wr);
    rNameV = regr_col_headers(:exper, nx);
    bExpV = [get_coefficient(rt, rNameV[j])  for j = 1 : nx];
    @assert all(-0.5 .< bExpV .< 0.5)
    return bExpV
end

# File name with experience coefficients
function exper_raw_file(ds :: DataSettings, s :: Symbol)
    wr = wage_regr_settings(ds);
    if length(exper_groups(wr)) == 1
        suffix = "_all--same";
    elseif exper_groups(wr) == [[:HSG, :SC], [:CG]]
        if s ∈ (:HSG, :SC, :SC)
            suffix = "_noncol--dif";
        elseif s == :CG
            suffix = "_colgrad--dif";
        else
            error("Invalid $s");
        end
    else
        error("Invalid $wr");
    end

    rf = RawDataFile(:selfReport, :none, :regression,
        "loginc_st1" * suffix * ".dat", ds);
    return rf
end

# Rupert / Zanella profiles for the 1942-46 cohorts
# College grads and others.
# Splice into an existing log efficiency profile to match the level at `maxExper`.
# For ages past 66: assume constant.
function splice_rupert_zanella!(logEffV, maxExper :: Integer, s)
    T = length(logEffV);
    ageWorkStart = work_start_age(s);
    age1 = ageWorkStart + maxExper - 1;
    age2 = min(66, age1 + T - maxExper);
    rzLogEffV = read_rupert_zanella(age1, age2, s);
    rzIdxV = (maxExper - 1) .+ (1 : length(rzLogEffV));
    logEffV[rzIdxV] .= rzLogEffV .- rzLogEffV[1] .+ logEffV[maxExper];
    # Deal with ages that extend past the RZ profiles
    if rzIdxV[end] < T
        logEffV[rzIdxV[end] : T] .= logEffV[rzIdxV[end]];
    end
    return logEffV
end

# Work start ages for converting RZ profiles by age into experience profiles.
# The same work start age for all non college grads because both estimations assume that all workers in that group have the same profile.
function work_start_age(s :: Symbol)
    if s == :HSG
        workStartAge = 20;
    elseif (s == :SC)  ||  (s == :SC)
        workStartAge = 20;
    elseif s == :CG
        workStartAge = 23;
    else
        error("Invalid $s");
    end
    return workStartAge
end

# Read Rupert/Zanella LOG efficiency by age
# Normalized to 1 for age 23.
function read_rupert_zanella(age1, age2, s)
    fPath = rupert_zanella_path(s);
    m, hdr = readdlm(fPath; comments = true, comment_char = '#', header = true);
    @assert (m isa Matrix{Float64})  "m is a $(typeof(m))";
    ageV = m[:,1];
    effV = m[:,2];
    interpolate_zeros!(effV);
    @assert age1 >= ageV[1]
    @assert (age2 <= ageV[end])  "Age2 too high: $age2 > $(ageV[end])"
    idx1 = findfirst(ageV .== age1);
    idx2 = findfirst(ageV .== age2);
    logEffV = log.(effV[idx1 : idx2]);
    @assert !any(isinf.(logEffV));
    return logEffV
end

function rupert_zanella_path(s)
    if s == :CG
        suffix = "college";
    else
        suffix = "no_college";
    end
    fPath = joinpath(dataDir, "rupert_zanella_" * suffix * ".txt");
    return fPath
end

function interpolate_zeros!(v :: Vector{Double})
    n = length(v);
    for j = 2 : (n-1)
        if v[j] == 0.0
            @assert v[j+1] != 0.0;
            v[j] = 0.5 * (v[j-1] + v[j+1]);
        end
    end
end

## -------------  Intercepts

"""
    $(SIGNATURES)

Intercepts of log wage regressions
In data units.
Regression contains intercept, school dummies (HSG = default), HS GPA dummies (1 = default), experience (dropped here).
RegressionDeviation contains `:cons` as intercept and school dummies.

Log wage = intercept + experience profile(experience)
It is legitimate to match these intercepts to model wages of workers with experience 1.
Substantive test is plotting the implied wage profiles.
"""
function wage_regr_intercepts(ds :: DataSettings)
    wr = wage_regr_settings(ds);
    @assert n_school(wr) == n_school(ds)

    fn = "loginc_st2_3" * regr_file_suffix(wr) * ".dat";
    rf = RawDataFile(:selfReport, :none, :regression, fn, ds);
    rt = read_regression_file(rf);
    rename_regressors(rt);
    return rt
end

"""
    $(SIGNATURES)

Predicted earnings at given experience and worker characteristics (at work start)
Also works for regression for grads. Just set `iSchool = 0` because that regressor is not available for grads.

Assumes that coefficients have been renamed.

# Arguments
- `quality`: last college quality. Not available for all regressions. Then ignored.
- `parental`: parental income group. Not available for all regressions. Then ignored.
"""
function workstart_earnings(rt :: RegressionTable, afqtGroup :: Integer,
    iSchool :: Integer;   quality :: Integer = 0,  parental :: Integer = 0)

    logEarn = get_intercept(rt) +
        get_regr_coef(rt, :afqt, afqtGroup) +
        get_regr_coef(rt, :school, iSchool) +
        get_regr_coef(rt, :parental, parental; errorIfMissing = false) +
        get_regr_coef(rt, :lastColl, quality; errorIfMissing = false);
    # end
    earn = exp(logEarn);
    return earn
end

## ------------  Wage regressions; grads; with quality dummies
# Omitted category is the first quality from which one can graduate.
function wage_regr_grads(ds :: DataSettings)
    wr = wage_regr_settings(ds);
    @assert n_school(wr) == n_school(ds)

    fn = "loginc_st2_2" * regr_file_suffix(wr) * ".dat";
    rf = RawDataFile(:selfReport, :none, :regression, fn, ds);
    rt = read_regression_file(rf);
    rename_regressors(rt);

    @assert validate_wage_regr_grads(ds, rt)  """
        Invalid wage regression for graduates.
        $ds
        $(data_file(rf))
    """
    return rt
end

function validate_wage_regr_grads(ds :: DataSettings, rt :: RegressionTable)
    isValid = true;
    # Cannot grad from q1
    if has_regressor(rt, regressor_name(:lastColl, 1))
        @warn "Should not have regressor lastColl1"
        isValid = false;
    end
    # Check that last lastColl is the default category
    if has_regressor(rt, regressor_name(:lastColl, 2))  ||
        !has_regressor(rt, regressor_name(:lastColl, n_colleges(ds)))
        @warn """Wrong default category in wage regression:
            $rt
            """
        isValid = false;
    end
    return isValid
end

# -----------


text:
# Dumbest possible nested integration method

struct Quad end

select(::Type{Bool}, r, p) = r ? [exp(p), 0] : [0, exp(p)]

function normalise(p)
  s = sum(p)
  s == 0 && error("Conditions are unsatisfiable")
  p ./ s
end

distribution(::Type{Bool}, ps) = collapse(Bernoulli(normalise(ps)[1]))

quad(f) = f()

quad(f, ::Type{<:Real}, Ts...) =
  quadgk(x -> quad((xs...) -> f(x, xs...), Ts...),
         -Inf, Inf)[1]

quad(f, ::Type{Bool}, Ts...) =
  quad((xs...) -> f(true, xs...), Ts...) +
  quad((xs...) -> f(false, xs...), Ts...)

function infer(f, ::Quad, tr = trace(typeof(f)))
  r = returntype(tr)
  r == Bool || return
  lprob, vars = logprob(tr)
  Ts = [T for (v, T) in vars]
  lprob = func(lprob)
  f = (vars...) -> select(r, Base.invokelatest(lprob, f, vars)...)
  distribution(r, quad(f, Ts...))
end


text:
"""
    ImplicitRungeKuttaSolver <: AbstractRungeKuttaSolver

A composite type for an implicit [`AbstractRungeKuttaSolver`](@ref).

# Constructors
```julia
ImplicitRungeKuttaSolver(tableau, h, newton[, adaptive])
IRK(args...; kwargs...)
```

# Arguments
- `tableau  :: ButcherTableau`     : Butcher tableau.
- `stepsize :: StepSize`           : step-size.
- `newton   :: NewtonParameters`   : simplified Newton's parameters.
- `adaptive :: AdaptiveParameters` : embedded method's parameters.

# Functions
- [`show`   ](@ref) : shows name and contents.
- [`summary`](@ref) : shows name.
"""
mutable struct ImplicitRungeKuttaSolver{tableau_T, stepsize_T, newton_T, adaptive_T} <: AbstractRungeKuttaSolver
    tableau::tableau_T
    stepsize::stepsize_T
    newton::newton_T
    adaptive::adaptive_T
end

ImplicitRungeKuttaSolver(tableau, h::Real, newton, adaptive) = ImplicitRungeKuttaSolver(tableau, StepSize(h), newton, adaptive)
ImplicitRungeKuttaSolver(tableau, stepsize, newton) = ImplicitRungeKuttaSolver(tableau, stepsize, newton, nothing)
@doc (@doc ImplicitRungeKuttaSolver) IRK(args...; kwargs...) = ImplicitRungeKuttaSolver(args...; kwargs...)

############################################################################################
#                                         PRINTING                                         #
############################################################################################

"""
    show(io::IO, solver::ImplicitRungeKuttaSolver)

prints a full description of `solver` and its contents to a stream `io`.
"""
Base.show(io::IO, solver::ImplicitRungeKuttaSolver) = NSDEBase._show(io, solver)

"""
    summary(io::IO, solver::ImplicitRungeKuttaSolver)

prints a brief description of `solver` to a stream `io`.
"""
Base.summary(io::IO, solver::ImplicitRungeKuttaSolver) = NSDEBase._summary(io, solver)

############################################################################################
#                                          METHODS                                         #
############################################################################################

function (solver::ImplicitRungeKuttaSolver)(problem::AbstractInitialValueProblem; save_stages::Bool = false)
    solve(problem, solver; save_stages=save_stages)
end