text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: frauddetector
using AWS.Compat
using AWS.UUIDs
"""
    BatchCreateVariable()

Creates a batch of variables.

# Required Parameters
- `variableEntries`: The list of variables for the batch create variable request.

# Optional Parameters
- `tags`: A collection of key and value pairs.
"""

batch_create_variable(variableEntries; aws_config::AWSConfig=global_aws_config()) = frauddetector("BatchCreateVariable", Dict{String, Any}("variableEntries"=>variableEntries); aws_config=aws_config)
batch_create_variable(variableEntries, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("BatchCreateVariable", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("variableEntries"=>variableEntries), args)); aws_config=aws_config)

"""
    BatchGetVariable()

Gets a batch of variables.

# Required Parameters
- `names`: The list of variable names to get.

"""

batch_get_variable(names; aws_config::AWSConfig=global_aws_config()) = frauddetector("BatchGetVariable", Dict{String, Any}("names"=>names); aws_config=aws_config)
batch_get_variable(names, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("BatchGetVariable", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("names"=>names), args)); aws_config=aws_config)

"""
    CreateDetectorVersion()

Creates a detector version. The detector version starts in a DRAFT status.

# Required Parameters
- `detectorId`: The ID of the detector under which you want to create a new version.
- `rules`: The rules to include in the detector version.

# Optional Parameters
- `description`: The description of the detector version.
- `externalModelEndpoints`: The Amazon Sagemaker model endpoints to include in the detector version.
- `modelVersions`: The model versions to include in the detector version.
- `ruleExecutionMode`: The rule execution mode for the rules included in the detector version. You can define and edit the rule mode at the detector version level, when it is in draft status. If you specify FIRST_MATCHED, Amazon Fraud Detector evaluates rules sequentially, first to last, stopping at the first matched rule. Amazon Fraud dectector then provides the outcomes for that single rule. If you specifiy ALL_MATCHED, Amazon Fraud Detector evaluates all rules and returns the outcomes for all matched rules.  The default behavior is FIRST_MATCHED.
- `tags`: A collection of key and value pairs.
"""

create_detector_version(detectorId, rules; aws_config::AWSConfig=global_aws_config()) = frauddetector("CreateDetectorVersion", Dict{String, Any}("detectorId"=>detectorId, "rules"=>rules); aws_config=aws_config)
create_detector_version(detectorId, rules, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("CreateDetectorVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "rules"=>rules), args)); aws_config=aws_config)

"""
    CreateModel()

Creates a model using the specified model type.

# Required Parameters
- `eventTypeName`: The name of the event type.
- `modelId`: The model ID.
- `modelType`: The model type.

# Optional Parameters
- `description`: The model description.
- `tags`: A collection of key and value pairs.
"""

create_model(eventTypeName, modelId, modelType; aws_config::AWSConfig=global_aws_config()) = frauddetector("CreateModel", Dict{String, Any}("eventTypeName"=>eventTypeName, "modelId"=>modelId, "modelType"=>modelType); aws_config=aws_config)
create_model(eventTypeName, modelId, modelType, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("CreateModel", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("eventTypeName"=>eventTypeName, "modelId"=>modelId, "modelType"=>modelType), args)); aws_config=aws_config)

"""
    CreateModelVersion()

Creates a version of the model using the specified model type and model id.

# Required Parameters
- `modelId`: The model ID.
- `modelType`: The model type.
- `trainingDataSchema`: The training data schema.
- `trainingDataSource`: The training data source location in Amazon S3.

# Optional Parameters
- `externalEventsDetail`: Details for the external events data used for model version training. Required if trainingDataSource is EXTERNAL_EVENTS.
- `tags`: A collection of key and value pairs.
"""

create_model_version(modelId, modelType, trainingDataSchema, trainingDataSource; aws_config::AWSConfig=global_aws_config()) = frauddetector("CreateModelVersion", Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "trainingDataSchema"=>trainingDataSchema, "trainingDataSource"=>trainingDataSource); aws_config=aws_config)
create_model_version(modelId, modelType, trainingDataSchema, trainingDataSource, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("CreateModelVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "trainingDataSchema"=>trainingDataSchema, "trainingDataSource"=>trainingDataSource), args)); aws_config=aws_config)

"""
    CreateRule()

Creates a rule for use with the specified detector.

# Required Parameters
- `detectorId`: The detector ID for the rule's parent detector.
- `expression`: The rule expression.
- `language`: The language of the rule.
- `outcomes`: The outcome or outcomes returned when the rule expression matches.
- `ruleId`: The rule ID.

# Optional Parameters
- `description`: The rule description.
- `tags`: A collection of key and value pairs.
"""

create_rule(detectorId, expression, language, outcomes, ruleId; aws_config::AWSConfig=global_aws_config()) = frauddetector("CreateRule", Dict{String, Any}("detectorId"=>detectorId, "expression"=>expression, "language"=>language, "outcomes"=>outcomes, "ruleId"=>ruleId); aws_config=aws_config)
create_rule(detectorId, expression, language, outcomes, ruleId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("CreateRule", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "expression"=>expression, "language"=>language, "outcomes"=>outcomes, "ruleId"=>ruleId), args)); aws_config=aws_config)

"""
    CreateVariable()

Creates a variable.

# Required Parameters
- `dataSource`: The source of the data.
- `dataType`: The data type.
- `defaultValue`: The default value for the variable when no value is received.
- `name`: The name of the variable.

# Optional Parameters
- `description`: The description.
- `tags`: A collection of key and value pairs.
- `variableType`: The variable type. For more information see Variable types.  Valid Values: AUTH_CODE | AVS | BILLING_ADDRESS_L1 | BILLING_ADDRESS_L2 | BILLING_CITY | BILLING_COUNTRY | BILLING_NAME | BILLING_PHONE | BILLING_STATE | BILLING_ZIP | CARD_BIN | CATEGORICAL | CURRENCY_CODE | EMAIL_ADDRESS | FINGERPRINT | FRAUD_LABEL | FREE_FORM_TEXT | IP_ADDRESS | NUMERIC | ORDER_ID | PAYMENT_TYPE | PHONE_NUMBER | PRICE | PRODUCT_CATEGORY | SHIPPING_ADDRESS_L1 | SHIPPING_ADDRESS_L2 | SHIPPING_CITY | SHIPPING_COUNTRY | SHIPPING_NAME | SHIPPING_PHONE | SHIPPING_STATE | SHIPPING_ZIP | USERAGENT
"""

create_variable(dataSource, dataType, defaultValue, name; aws_config::AWSConfig=global_aws_config()) = frauddetector("CreateVariable", Dict{String, Any}("dataSource"=>dataSource, "dataType"=>dataType, "defaultValue"=>defaultValue, "name"=>name); aws_config=aws_config)
create_variable(dataSource, dataType, defaultValue, name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("CreateVariable", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("dataSource"=>dataSource, "dataType"=>dataType, "defaultValue"=>defaultValue, "name"=>name), args)); aws_config=aws_config)

"""
    DeleteDetector()

Deletes the detector. Before deleting a detector, you must first delete all detector versions and rule versions associated with the detector.

# Required Parameters
- `detectorId`: The ID of the detector to delete.

"""

delete_detector(detectorId; aws_config::AWSConfig=global_aws_config()) = frauddetector("DeleteDetector", Dict{String, Any}("detectorId"=>detectorId); aws_config=aws_config)
delete_detector(detectorId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("DeleteDetector", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId), args)); aws_config=aws_config)

"""
    DeleteDetectorVersion()

Deletes the detector version. You cannot delete detector versions that are in ACTIVE status.

# Required Parameters
- `detectorId`: The ID of the parent detector for the detector version to delete.
- `detectorVersionId`: The ID of the detector version to delete.

"""

delete_detector_version(detectorId, detectorVersionId; aws_config::AWSConfig=global_aws_config()) = frauddetector("DeleteDetectorVersion", Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId); aws_config=aws_config)
delete_detector_version(detectorId, detectorVersionId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("DeleteDetectorVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId), args)); aws_config=aws_config)

"""
    DeleteEvent()

Deletes the specified event.

# Required Parameters
- `eventId`: The ID of the event to delete.
- `eventTypeName`: The name of the event type.

"""

delete_event(eventId, eventTypeName; aws_config::AWSConfig=global_aws_config()) = frauddetector("DeleteEvent", Dict{String, Any}("eventId"=>eventId, "eventTypeName"=>eventTypeName); aws_config=aws_config)
delete_event(eventId, eventTypeName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("DeleteEvent", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("eventId"=>eventId, "eventTypeName"=>eventTypeName), args)); aws_config=aws_config)

"""
    DeleteRule()

Deletes the rule. You cannot delete a rule if it is used by an ACTIVE or INACTIVE detector version.

# Required Parameters
- `rule`:

"""

delete_rule(rule; aws_config::AWSConfig=global_aws_config()) = frauddetector("DeleteRule", Dict{String, Any}("rule"=>rule); aws_config=aws_config)
delete_rule(rule, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("DeleteRule", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("rule"=>rule), args)); aws_config=aws_config)

"""
    DescribeDetector()

Gets all versions for a specified detector.

# Required Parameters
- `detectorId`: The detector ID.

# Optional Parameters
- `maxResults`: The maximum number of results to return for the request.
- `nextToken`: The next token from the previous response.
"""

describe_detector(detectorId; aws_config::AWSConfig=global_aws_config()) = frauddetector("DescribeDetector", Dict{String, Any}("detectorId"=>detectorId); aws_config=aws_config)
describe_detector(detectorId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("DescribeDetector", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId), args)); aws_config=aws_config)

"""
    DescribeModelVersions()

Gets all of the model versions for the specified model type or for the specified model type and model ID. You can also get details for a single, specified model version.

# Optional Parameters
- `maxResults`: The maximum number of results to return.
- `modelId`: The model ID.
- `modelType`: The model type.
- `modelVersionNumber`: The model version number.
- `nextToken`: The next token from the previous results.
"""

describe_model_versions(; aws_config::AWSConfig=global_aws_config()) = frauddetector("DescribeModelVersions"; aws_config=aws_config)
describe_model_versions(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("DescribeModelVersions", args; aws_config=aws_config)

"""
    GetDetectorVersion()

Gets a particular detector version.

# Required Parameters
- `detectorId`: The detector ID.
- `detectorVersionId`: The detector version ID.

"""

get_detector_version(detectorId, detectorVersionId; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetDetectorVersion", Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId); aws_config=aws_config)
get_detector_version(detectorId, detectorVersionId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetDetectorVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId), args)); aws_config=aws_config)

"""
    GetDetectors()

Gets all detectors or a single detector if a detectorId is specified. This is a paginated API. If you provide a null maxResults, this action retrieves a maximum of 10 records per page. If you provide a maxResults, the value must be between 5 and 10. To get the next page results, provide the pagination token from the GetDetectorsResponse as part of your request. A null pagination token fetches the records from the beginning.

# Optional Parameters
- `detectorId`: The detector ID.
- `maxResults`: The maximum number of objects to return for the request.
- `nextToken`: The next token for the subsequent request.
"""

get_detectors(; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetDetectors"; aws_config=aws_config)
get_detectors(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetDetectors", args; aws_config=aws_config)

"""
    GetEntityTypes()

Gets all entity types or a specific entity type if a name is specified. This is a paginated API. If you provide a null maxResults, this action retrieves a maximum of 10 records per page. If you provide a maxResults, the value must be between 5 and 10. To get the next page results, provide the pagination token from the GetEntityTypesResponse as part of your request. A null pagination token fetches the records from the beginning.

# Optional Parameters
- `maxResults`: The maximum number of objects to return for the request.
- `name`: The name.
- `nextToken`: The next token for the subsequent request.
"""

get_entity_types(; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetEntityTypes"; aws_config=aws_config)
get_entity_types(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetEntityTypes", args; aws_config=aws_config)

"""
    GetEventPrediction()

Evaluates an event against a detector version. If a version ID is not provided, the detector’s (ACTIVE) version is used.

# Required Parameters
- `detectorId`: The detector ID.
- `entities`: The entity type (associated with the detector's event type) and specific entity ID representing who performed the event. If an entity id is not available, use \"UNKNOWN.\"
- `eventId`: The unique ID used to identify the event.
- `eventTimestamp`: Timestamp that defines when the event under evaluation occurred.
- `eventTypeName`: The event type associated with the detector specified for the prediction.
- `eventVariables`: Names of the event type's variables you defined in Amazon Fraud Detector to represent data elements and their corresponding values for the event you are sending for evaluation.

# Optional Parameters
- `detectorVersionId`: The detector version ID.
- `externalModelEndpointDataBlobs`: The Amazon SageMaker model endpoint input data blobs.
"""

get_event_prediction(detectorId, entities, eventId, eventTimestamp, eventTypeName, eventVariables; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetEventPrediction", Dict{String, Any}("detectorId"=>detectorId, "entities"=>entities, "eventId"=>eventId, "eventTimestamp"=>eventTimestamp, "eventTypeName"=>eventTypeName, "eventVariables"=>eventVariables); aws_config=aws_config)
get_event_prediction(detectorId, entities, eventId, eventTimestamp, eventTypeName, eventVariables, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetEventPrediction", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "entities"=>entities, "eventId"=>eventId, "eventTimestamp"=>eventTimestamp, "eventTypeName"=>eventTypeName, "eventVariables"=>eventVariables), args)); aws_config=aws_config)

"""
    GetEventTypes()

Gets all event types or a specific event type if name is provided. This is a paginated API. If you provide a null maxResults, this action retrieves a maximum of 10 records per page. If you provide a maxResults, the value must be between 5 and 10. To get the next page results, provide the pagination token from the GetEventTypesResponse as part of your request. A null pagination token fetches the records from the beginning.

# Optional Parameters
- `maxResults`: The maximum number of objects to return for the request.
- `name`: The name.
- `nextToken`: The next token for the subsequent request.
"""

get_event_types(; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetEventTypes"; aws_config=aws_config)
get_event_types(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetEventTypes", args; aws_config=aws_config)

"""
    GetExternalModels()

Gets the details for one or more Amazon SageMaker models that have been imported into the service. This is a paginated API. If you provide a null maxResults, this actions retrieves a maximum of 10 records per page. If you provide a maxResults, the value must be between 5 and 10. To get the next page results, provide the pagination token from the GetExternalModelsResult as part of your request. A null pagination token fetches the records from the beginning.

# Optional Parameters
- `maxResults`: The maximum number of objects to return for the request.
- `modelEndpoint`: The Amazon SageMaker model endpoint.
- `nextToken`: The next page token for the request.
"""

get_external_models(; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetExternalModels"; aws_config=aws_config)
get_external_models(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetExternalModels", args; aws_config=aws_config)

"""
    GetKMSEncryptionKey()

Gets the encryption key if a Key Management Service (KMS) customer master key (CMK) has been specified to be used to encrypt content in Amazon Fraud Detector.

"""

get_kmsencryption_key(; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetKMSEncryptionKey"; aws_config=aws_config)
get_kmsencryption_key(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetKMSEncryptionKey", args; aws_config=aws_config)

"""
    GetLabels()

Gets all labels or a specific label if name is provided. This is a paginated API. If you provide a null maxResults, this action retrieves a maximum of 50 records per page. If you provide a maxResults, the value must be between 10 and 50. To get the next page results, provide the pagination token from the GetGetLabelsResponse as part of your request. A null pagination token fetches the records from the beginning.

# Optional Parameters
- `maxResults`: The maximum number of objects to return for the request.
- `name`: The name of the label or labels to get.
- `nextToken`: The next token for the subsequent request.
"""

get_labels(; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetLabels"; aws_config=aws_config)
get_labels(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetLabels", args; aws_config=aws_config)

"""
    GetModelVersion()

Gets the details of the specified model version.

# Required Parameters
- `modelId`: The model ID.
- `modelType`: The model type.
- `modelVersionNumber`: The model version number.

"""

get_model_version(modelId, modelType, modelVersionNumber; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetModelVersion", Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "modelVersionNumber"=>modelVersionNumber); aws_config=aws_config)
get_model_version(modelId, modelType, modelVersionNumber, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetModelVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "modelVersionNumber"=>modelVersionNumber), args)); aws_config=aws_config)

"""
    GetModels()

Gets one or more models. Gets all models for the AWS account if no model type and no model id provided. Gets all models for the AWS account and model type, if the model type is specified but model id is not provided. Gets a specific model if (model type, model id) tuple is specified.  This is a paginated API. If you provide a null maxResults, this action retrieves a maximum of 10 records per page. If you provide a maxResults, the value must be between 1 and 10. To get the next page results, provide the pagination token from the response as part of your request. A null pagination token fetches the records from the beginning.

# Optional Parameters
- `maxResults`: The maximum number of objects to return for the request.
- `modelId`: The model ID.
- `modelType`: The model type.
- `nextToken`: The next token for the subsequent request.
"""

get_models(; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetModels"; aws_config=aws_config)
get_models(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetModels", args; aws_config=aws_config)

"""
    GetOutcomes()

Gets one or more outcomes. This is a paginated API. If you provide a null maxResults, this actions retrieves a maximum of 100 records per page. If you provide a maxResults, the value must be between 50 and 100. To get the next page results, provide the pagination token from the GetOutcomesResult as part of your request. A null pagination token fetches the records from the beginning.

# Optional Parameters
- `maxResults`: The maximum number of objects to return for the request.
- `name`: The name of the outcome or outcomes to get.
- `nextToken`: The next page token for the request.
"""

get_outcomes(; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetOutcomes"; aws_config=aws_config)
get_outcomes(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetOutcomes", args; aws_config=aws_config)

"""
    GetRules()

Get all rules for a detector (paginated) if ruleId and ruleVersion are not specified. Gets all rules for the detector and the ruleId if present (paginated). Gets a specific rule if both the ruleId and the ruleVersion are specified. This is a paginated API. Providing null maxResults results in retrieving maximum of 100 records per page. If you provide maxResults the value must be between 50 and 100. To get the next page result, a provide a pagination token from GetRulesResult as part of your request. Null pagination token fetches the records from the beginning.

# Required Parameters
- `detectorId`: The detector ID.

# Optional Parameters
- `maxResults`: The maximum number of rules to return for the request.
- `nextToken`: The next page token.
- `ruleId`: The rule ID.
- `ruleVersion`: The rule version.
"""

get_rules(detectorId; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetRules", Dict{String, Any}("detectorId"=>detectorId); aws_config=aws_config)
get_rules(detectorId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetRules", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId), args)); aws_config=aws_config)

"""
    GetVariables()

Gets all of the variables or the specific variable. This is a paginated API. Providing null maxSizePerPage results in retrieving maximum of 100 records per page. If you provide maxSizePerPage the value must be between 50 and 100. To get the next page result, a provide a pagination token from GetVariablesResult as part of your request. Null pagination token fetches the records from the beginning.

# Optional Parameters
- `maxResults`: The max size per page determined for the get variable request.
- `name`: The name of the variable.
- `nextToken`: The next page token of the get variable request.
"""

get_variables(; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetVariables"; aws_config=aws_config)
get_variables(args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("GetVariables", args; aws_config=aws_config)

"""
    ListTagsForResource()

Lists all tags associated with the resource. This is a paginated API. To get the next page results, provide the pagination token from the response as part of your request. A null pagination token fetches the records from the beginning.

# Required Parameters
- `resourceARN`: The ARN that specifies the resource whose tags you want to list.

# Optional Parameters
- `maxResults`: The maximum number of objects to return for the request.
- `nextToken`: The next token from the previous results.
"""

list_tags_for_resource(resourceARN; aws_config::AWSConfig=global_aws_config()) = frauddetector("ListTagsForResource", Dict{String, Any}("resourceARN"=>resourceARN); aws_config=aws_config)
list_tags_for_resource(resourceARN, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("ListTagsForResource", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("resourceARN"=>resourceARN), args)); aws_config=aws_config)

"""
    PutDetector()

Creates or updates a detector.

# Required Parameters
- `detectorId`: The detector ID.
- `eventTypeName`: The name of the event type.

# Optional Parameters
- `description`: The description of the detector.
- `tags`: A collection of key and value pairs.
"""

put_detector(detectorId, eventTypeName; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutDetector", Dict{String, Any}("detectorId"=>detectorId, "eventTypeName"=>eventTypeName); aws_config=aws_config)
put_detector(detectorId, eventTypeName, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutDetector", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "eventTypeName"=>eventTypeName), args)); aws_config=aws_config)

"""
    PutEntityType()

Creates or updates an entity type. An entity represents who is performing the event. As part of a fraud prediction, you pass the entity ID to indicate the specific entity who performed the event. An entity type classifies the entity. Example classifications include customer, merchant, or account.

# Required Parameters
- `name`: The name of the entity type.

# Optional Parameters
- `description`: The description.
- `tags`: A collection of key and value pairs.
"""

put_entity_type(name; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutEntityType", Dict{String, Any}("name"=>name); aws_config=aws_config)
put_entity_type(name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutEntityType", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), args)); aws_config=aws_config)

"""
    PutEventType()

Creates or updates an event type. An event is a business activity that is evaluated for fraud risk. With Amazon Fraud Detector, you generate fraud predictions for events. An event type defines the structure for an event sent to Amazon Fraud Detector. This includes the variables sent as part of the event, the entity performing the event (such as a customer), and the labels that classify the event. Example event types include online payment transactions, account registrations, and authentications.

# Required Parameters
- `entityTypes`: The entity type for the event type. Example entity types: customer, merchant, account.
- `eventVariables`: The event type variables.
- `name`: The name.

# Optional Parameters
- `description`: The description of the event type.
- `labels`: The event type labels.
- `tags`: A collection of key and value pairs.
"""

put_event_type(entityTypes, eventVariables, name; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutEventType", Dict{String, Any}("entityTypes"=>entityTypes, "eventVariables"=>eventVariables, "name"=>name); aws_config=aws_config)
put_event_type(entityTypes, eventVariables, name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutEventType", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("entityTypes"=>entityTypes, "eventVariables"=>eventVariables, "name"=>name), args)); aws_config=aws_config)

"""
    PutExternalModel()

Creates or updates an Amazon SageMaker model endpoint. You can also use this action to update the configuration of the model endpoint, including the IAM role and/or the mapped variables.

# Required Parameters
- `inputConfiguration`: The model endpoint input configuration.
- `invokeModelEndpointRoleArn`: The IAM role used to invoke the model endpoint.
- `modelEndpoint`: The model endpoints name.
- `modelEndpointStatus`: The model endpoint’s status in Amazon Fraud Detector.
- `modelSource`: The source of the model.
- `outputConfiguration`: The model endpoint output configuration.

# Optional Parameters
- `tags`: A collection of key and value pairs.
"""

put_external_model(inputConfiguration, invokeModelEndpointRoleArn, modelEndpoint, modelEndpointStatus, modelSource, outputConfiguration; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutExternalModel", Dict{String, Any}("inputConfiguration"=>inputConfiguration, "invokeModelEndpointRoleArn"=>invokeModelEndpointRoleArn, "modelEndpoint"=>modelEndpoint, "modelEndpointStatus"=>modelEndpointStatus, "modelSource"=>modelSource, "outputConfiguration"=>outputConfiguration); aws_config=aws_config)
put_external_model(inputConfiguration, invokeModelEndpointRoleArn, modelEndpoint, modelEndpointStatus, modelSource, outputConfiguration, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutExternalModel", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("inputConfiguration"=>inputConfiguration, "invokeModelEndpointRoleArn"=>invokeModelEndpointRoleArn, "modelEndpoint"=>modelEndpoint, "modelEndpointStatus"=>modelEndpointStatus, "modelSource"=>modelSource, "outputConfiguration"=>outputConfiguration), args)); aws_config=aws_config)

"""
    PutKMSEncryptionKey()

Specifies the Key Management Service (KMS) customer master key (CMK) to be used to encrypt content in Amazon Fraud Detector.

# Required Parameters
- `kmsEncryptionKeyArn`: The KMS encryption key ARN.

"""

put_kmsencryption_key(kmsEncryptionKeyArn; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutKMSEncryptionKey", Dict{String, Any}("kmsEncryptionKeyArn"=>kmsEncryptionKeyArn); aws_config=aws_config)
put_kmsencryption_key(kmsEncryptionKeyArn, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutKMSEncryptionKey", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("kmsEncryptionKeyArn"=>kmsEncryptionKeyArn), args)); aws_config=aws_config)

"""
    PutLabel()

Creates or updates label. A label classifies an event as fraudulent or legitimate. Labels are associated with event types and used to train supervised machine learning models in Amazon Fraud Detector.

# Required Parameters
- `name`: The label name.

# Optional Parameters
- `description`: The label description.
- `tags`:
"""

put_label(name; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutLabel", Dict{String, Any}("name"=>name); aws_config=aws_config)
put_label(name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutLabel", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), args)); aws_config=aws_config)

"""
    PutOutcome()

Creates or updates an outcome.

# Required Parameters
- `name`: The name of the outcome.

# Optional Parameters
- `description`: The outcome description.
- `tags`: A collection of key and value pairs.
"""

put_outcome(name; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutOutcome", Dict{String, Any}("name"=>name); aws_config=aws_config)
put_outcome(name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("PutOutcome", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), args)); aws_config=aws_config)

"""
    TagResource()

Assigns tags to a resource.

# Required Parameters
- `resourceARN`: The resource ARN.
- `tags`: The tags to assign to the resource.

"""

tag_resource(resourceARN, tags; aws_config::AWSConfig=global_aws_config()) = frauddetector("TagResource", Dict{String, Any}("resourceARN"=>resourceARN, "tags"=>tags); aws_config=aws_config)
tag_resource(resourceARN, tags, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("TagResource", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("resourceARN"=>resourceARN, "tags"=>tags), args)); aws_config=aws_config)

"""
    UntagResource()

Removes tags from a resource.

# Required Parameters
- `resourceARN`: The ARN of the resource from which to remove the tag.
- `tagKeys`: The resource ARN.

"""

untag_resource(resourceARN, tagKeys; aws_config::AWSConfig=global_aws_config()) = frauddetector("UntagResource", Dict{String, Any}("resourceARN"=>resourceARN, "tagKeys"=>tagKeys); aws_config=aws_config)
untag_resource(resourceARN, tagKeys, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("UntagResource", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("resourceARN"=>resourceARN, "tagKeys"=>tagKeys), args)); aws_config=aws_config)

"""
    UpdateDetectorVersion()

 Updates a detector version. The detector version attributes that you can update include models, external model endpoints, rules, rule execution mode, and description. You can only update a DRAFT detector version.

# Required Parameters
- `detectorId`: The parent detector ID for the detector version you want to update.
- `detectorVersionId`: The detector version ID.
- `externalModelEndpoints`: The Amazon SageMaker model endpoints to include in the detector version.
- `rules`: The rules to include in the detector version.

# Optional Parameters
- `description`: The detector version description.
- `modelVersions`: The model versions to include in the detector version.
- `ruleExecutionMode`: The rule execution mode to add to the detector. If you specify FIRST_MATCHED, Amazon Fraud Detector evaluates rules sequentially, first to last, stopping at the first matched rule. Amazon Fraud dectector then provides the outcomes for that single rule. If you specifiy ALL_MATCHED, Amazon Fraud Detector evaluates all rules and returns the outcomes for all matched rules. You can define and edit the rule mode at the detector version level, when it is in draft status. The default behavior is FIRST_MATCHED.
"""

update_detector_version(detectorId, detectorVersionId, externalModelEndpoints, rules; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersion", Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId, "externalModelEndpoints"=>externalModelEndpoints, "rules"=>rules); aws_config=aws_config)
update_detector_version(detectorId, detectorVersionId, externalModelEndpoints, rules, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId, "externalModelEndpoints"=>externalModelEndpoints, "rules"=>rules), args)); aws_config=aws_config)

"""
    UpdateDetectorVersionMetadata()

Updates the detector version's description. You can update the metadata for any detector version (DRAFT, ACTIVE, or INACTIVE).

# Required Parameters
- `description`: The description.
- `detectorId`: The detector ID.
- `detectorVersionId`: The detector version ID.

"""

update_detector_version_metadata(description, detectorId, detectorVersionId; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersionMetadata", Dict{String, Any}("description"=>description, "detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId); aws_config=aws_config)
update_detector_version_metadata(description, detectorId, detectorVersionId, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersionMetadata", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("description"=>description, "detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId), args)); aws_config=aws_config)

"""
    UpdateDetectorVersionStatus()

Updates the detector version’s status. You can perform the following promotions or demotions using UpdateDetectorVersionStatus: DRAFT to ACTIVE, ACTIVE to INACTIVE, and INACTIVE to ACTIVE.

# Required Parameters
- `detectorId`: The detector ID.
- `detectorVersionId`: The detector version ID.
- `status`: The new status.

"""

update_detector_version_status(detectorId, detectorVersionId, status; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersionStatus", Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId, "status"=>status); aws_config=aws_config)
update_detector_version_status(detectorId, detectorVersionId, status, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateDetectorVersionStatus", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("detectorId"=>detectorId, "detectorVersionId"=>detectorVersionId, "status"=>status), args)); aws_config=aws_config)

"""
    UpdateModel()

Updates a model. You can update the description attribute using this action.

# Required Parameters
- `modelId`: The model ID.
- `modelType`: The model type.

# Optional Parameters
- `description`: The new model description.
"""

update_model(modelId, modelType; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateModel", Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType); aws_config=aws_config)
update_model(modelId, modelType, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateModel", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType), args)); aws_config=aws_config)

"""
    UpdateModelVersion()

Updates a model version. Updating a model version retrains an existing model version using updated training data and produces a new minor version of the model. You can update the training data set location and data access role attributes using this action. This action creates and trains a new minor version of the model, for example version 1.01, 1.02, 1.03.

# Required Parameters
- `majorVersionNumber`: The major version number.
- `modelId`: The model ID.
- `modelType`: The model type.

# Optional Parameters
- `externalEventsDetail`: The event details.
- `tags`: A collection of key and value pairs.
"""

update_model_version(majorVersionNumber, modelId, modelType; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateModelVersion", Dict{String, Any}("majorVersionNumber"=>majorVersionNumber, "modelId"=>modelId, "modelType"=>modelType); aws_config=aws_config)
update_model_version(majorVersionNumber, modelId, modelType, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateModelVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("majorVersionNumber"=>majorVersionNumber, "modelId"=>modelId, "modelType"=>modelType), args)); aws_config=aws_config)

"""
    UpdateModelVersionStatus()

Updates the status of a model version. You can perform the following status updates:   Change the TRAINING_COMPLETE status to ACTIVE.   Change ACTIVEto INACTIVE.

# Required Parameters
- `modelId`: The model ID of the model version to update.
- `modelType`: The model type.
- `modelVersionNumber`: The model version number.
- `status`: The model version status.

"""

update_model_version_status(modelId, modelType, modelVersionNumber, status; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateModelVersionStatus", Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "modelVersionNumber"=>modelVersionNumber, "status"=>status); aws_config=aws_config)
update_model_version_status(modelId, modelType, modelVersionNumber, status, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateModelVersionStatus", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("modelId"=>modelId, "modelType"=>modelType, "modelVersionNumber"=>modelVersionNumber, "status"=>status), args)); aws_config=aws_config)

"""
    UpdateRuleMetadata()

Updates a rule's metadata. The description attribute can be updated.

# Required Parameters
- `description`: The rule description.
- `rule`: The rule to update.

"""

update_rule_metadata(description, rule; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateRuleMetadata", Dict{String, Any}("description"=>description, "rule"=>rule); aws_config=aws_config)
update_rule_metadata(description, rule, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateRuleMetadata", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("description"=>description, "rule"=>rule), args)); aws_config=aws_config)

"""
    UpdateRuleVersion()

Updates a rule version resulting in a new rule version. Updates a rule version resulting in a new rule version (version 1, 2, 3 ...).

# Required Parameters
- `expression`: The rule expression.
- `language`: The language.
- `outcomes`: The outcomes.
- `rule`: The rule to update.

# Optional Parameters
- `description`: The description.
- `tags`: The tags to assign to the rule version.
"""

update_rule_version(expression, language, outcomes, rule; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateRuleVersion", Dict{String, Any}("expression"=>expression, "language"=>language, "outcomes"=>outcomes, "rule"=>rule); aws_config=aws_config)
update_rule_version(expression, language, outcomes, rule, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateRuleVersion", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("expression"=>expression, "language"=>language, "outcomes"=>outcomes, "rule"=>rule), args)); aws_config=aws_config)

"""
    UpdateVariable()

Updates a variable.

# Required Parameters
- `name`: The name of the variable.

# Optional Parameters
- `defaultValue`: The new default value of the variable.
- `description`: The new description.
- `variableType`: The variable type. For more information see Variable types.
"""

update_variable(name; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateVariable", Dict{String, Any}("name"=>name); aws_config=aws_config)
update_variable(name, args::AbstractDict{String, <:Any}; aws_config::AWSConfig=global_aws_config()) = frauddetector("UpdateVariable", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("name"=>name), args)); aws_config=aws_config)


text:
using Test
import ArchGDAL;
const AG = ArchGDAL;
using Tables

@testset "test_tables.jl" begin
    @testset "Tables Support" begin
        dataset = AG.read(joinpath(@__DIR__, "data/point.geojson"))
        dataset1 = AG.read(
            joinpath(@__DIR__, "data/multi_geom.csv"),
            options = [
                "GEOM_POSSIBLE_NAMES=point,linestring",
                "KEEP_GEOM_COLUMNS=NO",
            ],
        )
        dataset2 = AG.read(
            joinpath(@__DIR__, "data/missing_testcase.csv"),
            options = [
                "GEOM_POSSIBLE_NAMES=point,linestring",
                "KEEP_GEOM_COLUMNS=NO",
            ],
        )
        @test dataset isa ArchGDAL.IDataset
        @test dataset1 isa ArchGDAL.IDataset
        @test dataset2 isa ArchGDAL.IDataset
        layer = AG.getlayer(dataset, 0)
        layer1 = AG.getlayer(dataset1, 0)
        layer2 = AG.getlayer(dataset2, 0)

        @testset "Tables methods" begin
            @test Tables.schema(layer1) == Tables.Schema(
                (:point, :linestring, :id, :zoom, :location),
                (
                    AG.IGeometry{AG.wkbUnknown},
                    AG.IGeometry{AG.wkbUnknown},
                    String,
                    String,
                    String,
                ),
            )
            @test Tables.istable(typeof(layer)) == true
            @test Tables.rowaccess(typeof(layer)) == true

            features = collect(Tables.rows(layer1))
            @test length(features) == 2

            @test Tables.columnnames(features[1]) ==
                  (:point, :linestring, :id, :zoom, :location)
            @test ismissing(Tables.getcolumn(features[2], -5))
            @test ismissing(Tables.getcolumn(features[2], 0))
            @test Tables.getcolumn(features[1], 1) == "5.1"
            @test Tables.getcolumn(features[1], 2) == "1.0"
            @test Tables.getcolumn(features[1], 3) == "Mumbai"
            @test AG.toWKT(Tables.getcolumn(features[1], 4)) == "POINT (30 10)"
            @test AG.toWKT(Tables.getcolumn(features[1], 5)) ==
                  "LINESTRING (30 10,10 30,40 40)"
            @test Tables.getcolumn(features[1], :id) == "5.1"
            @test Tables.getcolumn(features[1], :zoom) == "1.0"
            @test Tables.getcolumn(features[1], :location) == "Mumbai"
            @test AG.toWKT(Tables.getcolumn(features[1], :point)) ==
                  "POINT (30 10)"
            @test AG.toWKT(Tables.getcolumn(features[1], :linestring)) ==
                  "LINESTRING (30 10,10 30,40 40)"
            @test ismissing(Tables.getcolumn(features[1], :fake))

            @test Tables.columnnames(features[2]) ==
                  (:point, :linestring, :id, :zoom, :location)
            @test ismissing(Tables.getcolumn(features[2], -5))
            @test ismissing(Tables.getcolumn(features[2], 0))
            @test Tables.getcolumn(features[2], 1) == "5.2"
            @test Tables.getcolumn(features[2], 2) == "2.0"
            @test Tables.getcolumn(features[2], 3) == "New Delhi"
            @test AG.toWKT(Tables.getcolumn(features[2], 4)) == "POINT (35 15)"
            @test AG.toWKT(Tables.getcolumn(features[2], 5)) ==
                  "LINESTRING (35 15,15 35,45 45)"
            @test Tables.getcolumn(features[2], :id) == "5.2"
            @test Tables.getcolumn(features[2], :zoom) == "2.0"
            @test Tables.getcolumn(features[2], :location) == "New Delhi"
            @test AG.toWKT(Tables.getcolumn(features[2], :point)) ==
                  "POINT (35 15)"
            @test AG.toWKT(Tables.getcolumn(features[2], :linestring)) ==
                  "LINESTRING (35 15,15 35,45 45)"
            @test ismissing(Tables.getcolumn(features[2], :fake))

            geom_names, field_names = AG.schema_names(AG.layerdefn(layer))
            @test collect(geom_names) == [Symbol("")]
            @test collect(field_names) == [:FID, :pointname]
            geom_names, field_names = AG.schema_names(AG.layerdefn(layer1))
            @test collect(geom_names) == [:point, :linestring]
            @test collect(field_names) == [:id, :zoom, :location]
        end
    end
end

ext: jl


text:
"""
$(TYPEDEF)

Real symmetric doubly nonnegative cone (intersection of nonnegative and positive
semidefinite cones) of dimension `dim` in svec format.

    $(FUNCTIONNAME){T}(dim::Int, use_dual::Bool = false)
"""
mutable struct DoublyNonnegativeTri{T <: Real} <: Cone{T}
    use_dual_barrier::Bool
    dim::Int
    side::Int
    rt2::T

    point::Vector{T}
    dual_point::Vector{T}
    grad::Vector{T}
    dder3::Vector{T}
    vec1::Vector{T}
    vec2::Vector{T}
    feas_updated::Bool
    grad_updated::Bool
    hess_updated::Bool
    inv_hess_updated::Bool
    hess_fact_updated::Bool
    is_feas::Bool
    hess::Symmetric{T, Matrix{T}}
    inv_hess::Symmetric{T, Matrix{T}}
    hess_fact_mat::Symmetric{T, Matrix{T}}
    hess_fact::Factorization{T}

    mat::Matrix{T}
    mat2::Matrix{T} # TODO rename to imply mutates fact_mat
    mat3::Matrix{T}
    mat4::Matrix{T} # TODO could remove if we factorize mat instead of mat2, currently mat is not used in any other oracles
    offdiag_idxs
    inv_mat::Matrix{T}
    inv_vec::Vector{T}
    fact_mat

    function DoublyNonnegativeTri{T}(
        dim::Int;
        use_dual::Bool = false,
        ) where {T <: Real}
        @assert dim >= 1
        cone = new{T}()
        cone.use_dual_barrier = use_dual
        cone.dim = dim
        cone.rt2 = sqrt(T(2))
        cone.side = side = svec_side(dim)
        cone.offdiag_idxs =
            vcat([svec_length(i - 1) .+ (1:(i - 1)) for i in 2:side]...)
        return cone
    end
end

reset_data(cone::DoublyNonnegativeTri) = (cone.feas_updated = cone.grad_updated =
    cone.hess_updated = cone.inv_hess_updated = cone.hess_fact_updated = false)

function setup_extra_data!(cone::DoublyNonnegativeTri{T}) where {T <: Real}
    cone.mat = zeros(T, cone.side, cone.side)
    cone.mat2 = zero(cone.mat)
    cone.mat3 = zero(cone.mat)
    cone.mat4 = zero(cone.mat)
    cone.inv_mat = zero(cone.mat)
    cone.inv_vec = zeros(T, length(cone.offdiag_idxs))
    return
end

get_nu(cone::DoublyNonnegativeTri) = cone.dim

function set_initial_point!(
    arr::AbstractVector{T},
    cone::DoublyNonnegativeTri{T},
    ) where T
    side = cone.side

    # for small side dimension, use closed-form solutions
    if side == 1
        on_diag = off_diag = one(T)
    elseif side == 2
        (on_diag, off_diag) = (sqrt(T(5)) / 2, inv(cone.rt2))
    else
        n = T(side)
        d = T(cone.dim)
        # root of this polynomial gives off-diagonal
        p1 = [-n - 1, 0, n ^ 2 + n + 7, 0, -2 * n ^ 2 - 8, 0, n ^ 2]
        # fallback values
        (on_diag, off_diag) = (n + 1, one(T))
        found_soln = false
        for offd_try in PolynomialRoots.roots(p1)
            offd_real = real(offd_try)
            # TODO this poly seems to always have real roots, prove
            if offd_real > 0
                # get trial point on the diagonal
                temp = d - (d - n) * abs2(offd_real)
                if temp > sqrt(eps(T))
                    ond_try = sqrt(temp / n)
                    denom = abs2(ond_try) + (n - 2) / cone.rt2 * ond_try *
                        offd_real - (n - 1) * abs2(offd_real) / 2
                    # check s = -g(s) conditions
                    if ond_try * cone.rt2 + (n - 2) * offd_real ≈ ond_try *
                        denom * cone.rt2 && denom ≈ abs2(offd_real) * (denom + 1)
                        (on_diag, off_diag) = (ond_try, offd_real)
                        found_soln = true
                        break
                    end
                end
            end
        end
        if !found_soln
            @warn("initial point inaccurate for DoublyNonnegativeTri " *
                "cone dimension $(cone.dim)")
        end
    end

    arr .= off_diag
    k = 1
    @inbounds for i in 1:cone.side
        arr[k] = on_diag
        k += i + 1
    end

    return arr
end

function update_feas(cone::DoublyNonnegativeTri{T}) where T
    @assert !cone.feas_updated

    if all(>(eps(T)), cone.point)
        svec_to_smat!(cone.mat, cone.point, cone.rt2)
        copyto!(cone.mat2, cone.mat)
        cone.fact_mat = cholesky!(Symmetric(cone.mat2, :U), check = false)
        cone.is_feas = isposdef(cone.fact_mat)
    else
        cone.is_feas = false
    end

    cone.feas_updated = true
    return cone.is_feas
end

function update_grad(cone::DoublyNonnegativeTri)
    @assert cone.is_feas

    inv_fact!(cone.inv_mat, cone.fact_mat)
    smat_to_svec!(cone.grad, cone.inv_mat, cone.rt2)
    cone.grad .*= -1
    @. @views cone.inv_vec = inv(cone.point[cone.offdiag_idxs])
    @. cone.grad[cone.offdiag_idxs] -= cone.inv_vec

    cone.grad_updated = true
    return cone.grad
end

function update_hess(cone::DoublyNonnegativeTri)
    @assert cone.grad_updated
    isdefined(cone, :hess) || alloc_hess!(cone)
    H = cone.hess.data

    copytri!(cone.inv_mat, 'U')
    symm_kron!(H, cone.inv_mat, cone.rt2)
    for (inv_od, idx) in zip(cone.inv_vec, cone.offdiag_idxs)
        H[idx, idx] += abs2(inv_od)
    end

    cone.hess_updated = true
    return cone.hess
end

function hess_prod!(
    prod::AbstractVecOrMat,
    arr::AbstractVecOrMat,
    cone::DoublyNonnegativeTri,
    )
    @assert is_feas(cone)

    @inbounds for i in 1:size(arr, 2)
        svec_to_smat!(cone.mat3, view(arr, :, i), cone.rt2)
        copytri!(cone.mat3, 'U')
        rdiv!(cone.mat3, cone.fact_mat)
        ldiv!(cone.fact_mat, cone.mat3)
        smat_to_svec!(view(prod, :, i), cone.mat3, cone.rt2)
    end
    offdiags = cone.offdiag_idxs
    @views s_off = cone.point[offdiags]
    @. @views prod[offdiags, :] += arr[offdiags, :] / s_off / s_off

    return prod
end

function dder3(cone::DoublyNonnegativeTri, dir::AbstractVector)
    @assert cone.grad_updated

    S = copytri!(svec_to_smat!(cone.mat4, dir, cone.rt2), 'U')
    ldiv!(cone.fact_mat, S)
    rdiv!(S, cone.fact_mat.U)
    mul!(cone.mat3, S, S') # TODO use outer prod function
    smat_to_svec!(cone.dder3, cone.mat3, cone.rt2)
    offdiags = cone.offdiag_idxs
    @views s_off = cone.point[offdiags]
    @. @views cone.dder3[offdiags] += abs2(dir[offdiags] / s_off) / s_off

    return cone.dder3
end


text:
"""
    _InitialValue

A singleton type for representing "universal" initial value (identity element).

The idea is that, given `op` for `mapfoldl`, virtually, we define an "extended"
version of it by

    op′(::_InitialValue, x) = x
    op′(acc, x) = op(acc, x)

This is just a conceptually useful model to have in mind and we don't actually
define `op′` here  (yet?).  But see `Base.BottomRF` for how it might work in
action.

(It is related to that you can always turn a semigroup without an identity into
a monoid by "adjoining" an element that acts as the identity.)
"""
struct _InitialValue end

@inline _first(a1, as...) = a1

################
## map / map! ##
################

# In 0.6 the three methods below could be replaced with
# `map(f, as::Union{<:StaticArray,AbstractArray}...)` which included at least one `StaticArray`
# this is not the case on 0.7 and we instead hope to find a StaticArray in the first two arguments.
@inline function Base.map(f, a1::TupleVector, as::AbstractArray...)
    _map(f, a1, as...)
end
@inline function Base.map(f, a1::AbstractArray, a2::TupleVector, as::AbstractArray...)
    _map(f, a1, a2, as...)
end
@inline function Base.map(f, a1::TupleVector, a2::TupleVector, as::AbstractArray...)
    _map(f, a1, a2, as...)
end

@generated function _map(f, a::AbstractArray...)
    first_tuplevector = findfirst(ai -> ai <: TupleVector, a)
    if first_tuplevector === nothing
        return :(throw(ArgumentError("No TupleVector found in argument list")))
    end
    # Passing the Val as an argument to _map leads to inference issues when
    # recursively mapping over nested TupleVectors (see issue #593). Calling
    # Val in the generator here is valid because a[first_staticarray] is known to be a
    # TupleVector for which the default Val method is correct. If wrapped
    # TupleVector (with a custom Val method) are to be supported, this will
    # no longer be valid.
    S = length(a[first_tuplevector])

    if S == 0
        # In the empty case only, use inference to try figuring out a sensible
        # eltype, as is done in Base.collect and broadcast.
        # See https://github.com/JuliaArrays/StaticArrays.jl/issues/528
        eltys = [:(eltype(a[$i])) for i ∈ 1:length(a)]
        return quote
            @_inline_meta
            S = same_size(a...)
            T = Core.Compiler.return_type(f, Tuple{$(eltys...)})
            @inbounds return similar_type(a[$first_staticarray], T, S)()
        end
    end

    exprs = Vector{Expr}(undef, S)
    for i ∈ 1:S
        tmp = [:(a[$j][$i]) for j ∈ 1:length(a)]
        exprs[i] = :(f($(tmp...)))
    end

    return quote
        @_inline_meta
        S = same_size(a...)
        @inbounds elements = tuple($(exprs...))
        @inbounds return similar_type(typeof(_first(a...)), eltype(elements), S)(elements)
    end
end

@inline function Base.map!(f, dest::TupleVector{n}, a::TupleVector{n}...) where n
    _map!(f, dest, Val(n), a...)
end

# Ambiguities with Base:
@inline function map!(f, dest::TupleVector{n}, a::TupleVector{n}) where n
    _map!(f, dest, Val(n), a)
end
@inline function map!(f,dest::TupleVector{n},a::TupleVector{n},b::TupleVector{n}) where n
    _map!(f, dest, Val(n), a, b)
end

@generated function _map!(f, dest, ::Val{S}, a::TupleVector...) where {S}
    exprs = Vector{Expr}(undef, S)
    for i ∈ 1:S
        tmp = [:(a[$j][$i]) for j ∈ 1:length(a)]
        exprs[i] = :(dest[$i] = f($(tmp...)))
    end
    return quote
        @_inline_meta
        @inbounds $(Expr(:block, exprs...))
    end
end

###############
## mapreduce ##
###############

@inline function Base.mapreduce(f, op, a::TupleVector, b::TupleVector...; dims=:, init = _InitialValue())
    _mapreduce(f, op, dims, init, same_size(a, b...), a, b...)
end

@inline _mapreduce(args::Vararg{Any,N}) where N = _mapfoldl(args...)

@generated function _mapfoldl(f, op, dims::Colon, init, ::Val{S}, a::TupleVector...) where {S}
    if S == 0
        if init === _InitialValue
            if length(a) == 1
                return :(Base.mapreduce_empty(f, op, $(eltype(a[1]))))
            else
                return :(throw(ArgumentError("reducing over an empty collection is not allowed")))
            end
        else
            return :init
        end
    end
    tmp = [:(a[$j][1]) for j ∈ 1:length(a)]
    expr = :(f($(tmp...)))
    if init === _InitialValue
        expr = :(Base.reduce_first(op, $expr))
    else
        expr = :(op(init, $expr))
    end
    for i ∈ 2:S
        tmp = [:(a[$j][$i]) for j ∈ 1:length(a)]
        expr = :(op($expr, f($(tmp...))))
    end
    return quote
        @_inline_meta
        @inbounds return $expr
    end
end

@inline function _mapreduce(f, op, D::Int, init, sz::Val{S}, a::TupleVector) where {S}
    # Body of this function is split because constant propagation (at least
    # as of Julia 1.2) can't always correctly propagate here and
    # as a result the function is not type stable and very slow.
    # This makes it at least fast for three dimensions but people should use
    # for example any(a; dims=Val(1)) instead of any(a; dims=1) anyway.
    if D == 1
        return _mapreduce(f, op, Val(1), init, sz, a)
    else
        return _mapreduce(f, op, Val(D), init, sz, a)
    end
end

@generated function _mapfoldl(f, op, dims::Val{1}, init,
                               ::Val{S}, a::TupleVector) where {S,D}

    exprs = Array{Expr}(undef, 1)
    for i ∈ Base.product(1:1)
        expr = :(f(a[$(i...)]))
        if init === _InitialValue
            expr = :(Base.reduce_first(op, $expr))
        else
            expr = :(op(init, $expr))
        end

        exprs[i...] = expr
    end

    return quote
        @_inline_meta
        @inbounds elements = tuple($(exprs...))
        @inbounds return similar_type(a, eltype(elements), Val(1))(elements)
    end
end

############
## reduce ##
############

@inline Base.reduce(op, a::TupleVector; dims = :, init = _InitialValue()) =
    _reduce(op, a, dims, init)

# disambiguation
Base.reduce(::typeof(vcat), A::TupleVector{n,<:AbstractVecOrMat}) where n =
    Base._typed_vcat(mapreduce(eltype, promote_type, A), A)
Base.reduce(::typeof(vcat), A::TupleVector{n,<:TupleVectorLike}) where n =
    _reduce(vcat, A, :, _InitialValue())

Base.reduce(::typeof(hcat), A::TupleVector{n,<:AbstractVecOrMat}) where n =
    Base._typed_hcat(mapreduce(eltype, promote_type, A), A)
Base.reduce(::typeof(hcat), A::TupleVector{n,<:TupleVectorLike}) where n =
    _reduce(hcat, A, :, _InitialValue())

@inline _reduce(op, a::TupleVector, dims, init = _InitialValue()) =
    _mapreduce(identity, op, dims, init, length_val(a), a)

################
## (map)foldl ##
################

# Using `where {R}` to force specialization. See:
# https://docs.julialang.org/en/v1.5-dev/manual/performance-tips/#Be-aware-of-when-Julia-avoids-specializing-1
# https://github.com/JuliaLang/julia/pull/33917

@inline Base.mapfoldl(f::F, op::R, a::TupleVector; init = _InitialValue()) where {F,R} =
    _mapfoldl(f, op, :, init, length_val(a), a)
@inline Base.foldl(op::R, a::TupleVector; init = _InitialValue()) where {R} =
    _foldl(op, a, :, init)
@inline _foldl(op::R, a, dims, init = _InitialValue()) where {R} =
    _mapfoldl(identity, op, dims, init, length_val(a), a)

#######################
## related functions ##
#######################

# These are all similar in Base but not @inline'd
#
# Implementation notes:
#
# 1. mapreduce and mapreducedim usually do not take initial value, because we don't
# always know the return type of an arbitrary mapping function f.  (We usually want to use
# some initial value such as one(T) or zero(T), where T is the return type of f, but
# if users provide type-unstable f, its return type cannot be known.)  Therefore, mapped
# versions of the functions implemented below usually require the collection to have at
# least two entries.
#
# 2. Exceptions are the ones that require Boolean mapping functions.  For example, f in
# all and any must return Bool, so we know the appropriate initial value is true and false,
# respectively.  Therefore, all(f, ...) and any(f, ...) are implemented by mapreduce(f, ...)
# with an initial value v0 = true and false.
#
# TODO: change to use Base.reduce_empty/Base.reduce_first
@inline Base.iszero(a::TupleVector{N,T}) where {N,T} = reduce((x,y) -> x && iszero(y), a, init=true)

@inline Base.sum(a::TupleVector{N,T}; dims=:) where {N,T} = _reduce(+, a, dims)
@inline Base.sum(f, a::TupleVector{N,T}; dims=:) where {N,T} = _mapreduce(f, +, dims, _InitialValue(), Val(N), a)
@inline Base.sum(f::Union{Function, Type}, a::TupleVector{N,T}; dims=:) where {N,T} = _mapreduce(f, +, dims, _InitialValue(), Val(N), a) # avoid ambiguity

@inline Base.prod(a::TupleVector{N,T}; dims=:) where {N,T} = _reduce(*, a, dims)
@inline Base.prod(f, a::TupleVector{N,T}; dims=:) where {N,T} = _mapreduce(f, *, dims, _InitialValue(), Val(N), a)
@inline Base.prod(f::Union{Function, Type}, a::TupleVector{N,T}; dims=:) where {N,T} = _mapreduce(f, *, dims, _InitialValue(), Val(N), a)

@inline Base.count(a::TupleVector{N,Bool}; dims=:) where N = _reduce(+, a, dims)
@inline Base.count(f, a::TupleVector{N}; dims=:) where N = _mapreduce(x->f(x)::Bool, +, dims, _InitialValue(), Val(N), a)

@inline Base.all(a::TupleVector{N,Bool}; dims=:) where N = _reduce(&, a, dims, true)  # non-branching versions
@inline Base.all(f::Function, a::TupleVector{N}; dims=:) where N = _mapreduce(x->f(x)::Bool, &, dims, true, Val(N), a)

@inline Base.any(a::TupleVector{N,Bool}; dims=:) where N = _reduce(|, a, dims, false) # (benchmarking needed)
@inline Base.any(f::Function, a::TupleVector{N}; dims=:) where N = _mapreduce(x->f(x)::Bool, |, dims, false, Val(N), a) # (benchmarking needed)

@inline Base.in(x, a::TupleVector{N}) where N = _mapreduce(==(x), |, :, false, Val(N), a)

#=_mean_denom(a, dims::Colon) = length(a)
_mean_denom(a, dims::Int) = size(a, dims)
_mean_denom(a, ::Val{D}) where {D} = size(a, D)
_mean_denom(a, ::Type{Val{D}}) where {D} = size(a, D)

@inline Statistics.mean(a::TupleVector; dims=:) = _reduce(+, a, dims) / _mean_denom(a, dims)
@inline Statistics.mean(f::Function, a::TupleVector{N}; dims=:) = _mapreduce(f, +, dims, _InitialValue(), Val(N), a) / _mean_denom(a, dims)=#

@inline Base.minimum(a::TupleVector; dims=:) = _reduce(min, a, dims) # base has mapreduce(idenity, scalarmin, a)
@inline Base.minimum(f::Function, a::TupleVector{N}; dims=:) where N = _mapreduce(f, min, dims, _InitialValue(), Val{N}, a)

@inline Base.maximum(a::TupleVector; dims=:) = _reduce(max, a, dims) # base has mapreduce(idenity, scalarmax, a)
@inline Base.maximum(f::Function, a::TupleVector; dims=:) = _mapreduce(f, max, dims, _InitialValue(), Val(N), a)

# Diff is slightly different
@inline LinearAlgebra.diff(a::TupleVector{N};dims=Val(1)) where N = _diff(Val(N),a,dims)

@inline function _diff(sz::Val, a::TupleVector, D::Int)
    _diff(sz,a,Val(D))
end
@generated function _diff(::Val{N}, a::TupleVector, ::Val{1}) where N
    Snew = N-1
    exprs = Array{Expr}(undef, Snew)
    for i1 = Base.product(1:Snew)
        i2 = copy([i1...])
        i2[1] = i1[1] + 1
        exprs[i1...] = :(a[$(i2...)] - a[$(i1...)])
    end
    return quote
        @_inline_meta
        elements = tuple($(exprs...))
        @inbounds return similar_type(a, eltype(elements), Val($Snew))(elements)
    end
end

_maybe_val(dims::Integer) = Val(Int(dims))
_maybe_val(dims) = dims
_valof(::Val{D}) where D = D

@inline Base.accumulate(op::F, a::TupleVector; dims = :, init = _InitialValue()) where {F} =
    _accumulate(op, a, _maybe_val(dims), init)

@inline function _accumulate(op::F, a::TupleVector, dims::Union{Val,Colon}, init) where {F}
    # Adjoin the initial value to `op` (one-line version of `Base.BottomRF`):
    rf(x, y) = x isa _InitialValue ? Base.reduce_first(op, y) : op(x, y)

    if isempty(a)
        T = return_type(rf, Tuple{typeof(init), eltype(a)})
        return similar_type(a, T)()
    end

    results = _foldl(
        a,
        dims,
        (similar_type(a, Union{}, Val(0))(), init),
    ) do (ys, acc), x
        y = rf(acc, x)
        # Not using `push(ys, y)` here since we need to widen element type as
        # we iterate.
        (vcat(ys, TV[y]), y)
    end
    dims === (:) && return first(results)

    ys = map(first, results)
    # Now map over all indices of `a`.  Since `_map` needs at least
    # one `TupleVector` to be passed, we pass `a` here, even though
    # the values of `a` are not used.
    data = _map(a, CartesianIndices(a)) do _, CI
        D = _valof(dims)
        I = Tuple(CI)
        J = Base.setindex(I, 1, D)
        ys[J...][I[D]]
    end
    return similar_type(a, eltype(data))(data)
end

@inline Base.cumsum(a::TupleVector; kw...) = accumulate(Base.add_sum, a; kw...)
@inline Base.cumprod(a::TupleVector; kw...) = accumulate(Base.mul_prod, a; kw...)


text:
"""
    The structure represents the good ideal

"""
mutable struct IdealContext
    I
    yoverx
    basepolyring
    nvariables
    ground
    ystrings
    evalring

    # if the the ideal is saturated
    saturated::Bool
    t
    Q
end

function idealize(elem)
    idealize([elem])
end

function idealize(genset::Array{T}; saturated=false) where {T}
    basepolyring = parent(numerator( first(genset) ))
    nvariables = length(gens(basepolyring))
    ground = base_ring(basepolyring)
    ystrings = ["y$i" for i in 1:nvariables]
    yoverx, yoverxvars = Nemo.PolynomialRing(
                                         basepolyring,
                                         ystrings,
                                         ordering=:lex
    )

    context = IdealContext(
                         [],
                         yoverx,
                         basepolyring,
                         nvariables,
                         ground,
                         ystrings,
                         1,
                         saturated,
                         1,
                         1
    )

    idealize(genset, context, saturated=saturated)
end

function idealize(
               genset::Array{T}, context::IdealContext;
               saturated=false) where {T}

    yoverx = context.yoverx
    basepolyring = context.basepolyring
    nvariables = context.nvariables
    ground = context.ground
    ystrings = context.ystrings

    dens = map(denominator, genset)
    Q = dens[1]
    for d in dens
        Q = lcm(Q, d)
    end

    Fs = map(numerator ∘ (g -> g * Q), genset)

    Fx = Fs
    Fy = map(F -> change_base_ring(basepolyring, F, parent=yoverx), Fs)
    Qx = Q
    Qy = change_base_ring(basepolyring, Q, parent=yoverx)

    I = [
        Fyi * Qx - Fxi * Qy
        for (Fyi, Fxi) in zip(Fy, Fx)
    ]

    # TODO: align saturation types
    if saturated
        I, t = saturate(I, Q)
    else
        t = Nemo.gen(yoverx, 1)
    end

    evalstrings = deepcopy(ystrings)
    if saturated
        push!(evalstrings, "t")
    end

    singular_ground = tosingular(ground)
    evalring, evalvars = Singular.PolynomialRing(
                       singular_ground,
                       evalstrings,
                       ordering=ordering_lp(nvariables)*ordering_c()
    )

    return IdealContext(
               I,
               yoverx,
               basepolyring,
               nvariables,
               ground,
               ystrings,
               evalring,
               saturated,
               t,
               Q
    )
end

function idealize(
                elem, context::IdealContext;
                saturated=false) where {T}
    idealize([elem], context)
end


text:
__precompile__()

module Cbc
# This 'using' is required to suppress a warning about Clp not having Libdl in its
# dependencies (Libdl is used by BinaryProvider), e.g.: bicycle1885/CodecZlib.jl#26.
using Libdl

if isfile(joinpath(dirname(@__FILE__),"..","deps","deps.jl"))
    include("../deps/deps.jl")
else
    error("Cbc not properly installed. Please run Pkg.build(\"Cbc\")")
end

include("CbcCInterface.jl")
include("MPB_wrapper.jl")
include("MOI_wrapper.jl")

using Cbc.CbcMathProgSolverInterface
export CbcSolver

end # module


text:
## speedup window sum at inds

image_size = size(img)
pixels = length(img)

result = zeros(pixels)
pixels = reshape(img, pixels)
window = [25, 25]
inds = rand(CartesianIndices(img), 50)

function window_sum3_at_inds!(result, pixels, img_size, window, inds)
    w = Int64.((window[1]-1)/2)
    summed = padarray(reshape(pixels, img_size), Pad(:symmetric, (w, w)))
    summed = cumsum2d!(summed, summed)
    B = padarray(summed, Fill(0, (1, 1), (0, 0)))
    c = img_size[1]

    reshape(result, img_size) .= view(B, (1+w):(w+c), (1+w):(w+c)) .-
                                 view(B, (1+w):(w+c), (-w):(c-w-1)) .-
                                 view(B, (-w):(c-w-1), (1+w):(w+c)) .+
                                 view(B, (-w):(c-w-1), (-w):(c-w-1))
end

## whole image
import LAP_julia: window_sum3!, cumsum2d!, window_sum!

img_size = size(img)
pixel_count = length(img)

result = zeros(pixel_count)
result1 = zeros(pixel_count)
pixels = reshape(img, pixels)
window = [25, 25]
inds = rand(CartesianIndices(img), 50)

@benchmark window_sum3!(result, pixels, img_size, window, timer)
@benchmark window_sum3_new_pad!(result1, pixels, img_size, window, timer)

result == result1

timer = TimerOutput("timer")
@timeit timer "whole" begin
    B = window_sum3_new_pad!(result, pixels, img_size, window, timer)
end
print_timer(timer)

## attempt at speedup

function window_sum3_at_inds!(result, pixels, img_size, window, inds)

    w = Int64.((window[1]-1)/2)
    summed = padarray(reshape(pixels, img_size), Pad(:symmetric, (w+1, w+1), (w, w)))
    @views summed[-w, :] .= 0
    @views summed[:, -w] .= 0
    summed = cumsum2d!(summed, summed)

    a = CartesianIndex(w, w)
    b = CartesianIndex(w, -w-1)
    c = CartesianIndex(-w-1, w)
    d = CartesianIndex(-w-1, -w-1)
    for (matrix_ind, result_ind)  in zip(inds, CartesianIndices(result))
        res[result_ind] = summed[matrix_ind+a] -
                          summed[matrix_ind+b] -
                          summed[matrix_ind+c] +
                          summed[matrix_ind+d]
    end
    return res
end

res_inds = deepcopy(result)
res = deepcopy(result)

res = window_sum3!(res, pixels, img_size, window)
res_inds = window_sum3_at_inds!(res_inds, pixels, img_size, window, CartesianIndices(img_size))

@benchmark window_sum3!(res, pixels, img_size, window)
@benchmark window_sum3_at_inds!(res_inds, pixels, img_size, window, rand(CartesianIndices(img_size), 300))

result2 = deepcopy(result1)

res = window_sum3!(result1, pixels, img_size, window)
res_old = window_sum!(result2, pixels, img_size, window)

res_new_pad == res

B1 == B

result == result1

A = reshape(1:90000, 300, 300)

out = padarray(A, Pad(:symmetric, (2, 2), (1, 1)))

@benchmark out[:, 1] .= 0
@benchmark @views out[:, 1] .= 0

@benchmark out[1, :] .= 0
@benchmark @views out[1, :] .= 0

t = randn(5,5,2)
[ sum( t[ 1,1,: ] ), sum( t[ 5,5,: ] ) ]

sum.()

sum((x->x[I]).([A,B,C,D]))


text:
using Symbolics
using Test
using IfElse

# Derivatives
@variables t σ ρ β
@variables x y z
@variables uu(t) uuˍt(t)
D = Differential(t)
D2 = Differential(t)^2
Dx = Differential(x)

@test Symbol(D(D(uu))) === Symbol("uuˍtt(t)")
@test Symbol(D(uuˍt)) === Symbol(D(D(uu)))

test_equal(a, b) = @test isequal(simplify(a), simplify(b))

#@test @macroexpand(@derivatives D'~t D2''~t) == @macroexpand(@derivatives (D'~t), (D2''~t))

@test isequal(expand_derivatives(D(t)), 1)
@test isequal(expand_derivatives(D(D(t))), 0)

dsin = D(sin(t))
@test isequal(expand_derivatives(dsin), cos(t))

dcsch = D(csch(t))
@test isequal(expand_derivatives(dcsch), simplify(-coth(t) * csch(t)))

@test isequal(expand_derivatives(D(-7)), 0)
@test isequal(expand_derivatives(D(sin(2t))), simplify(cos(2t) * 2))
@test isequal(expand_derivatives(D2(sin(t))), simplify(-sin(t)))
@test isequal(expand_derivatives(D2(sin(2t))), simplify(-sin(2t) * 4))
@test isequal(expand_derivatives(D2(t)), 0)
@test isequal(expand_derivatives(D2(5)), 0)

# Chain rule
dsinsin = D(sin(sin(t)))
test_equal(expand_derivatives(dsinsin), cos(sin(t))*cos(t))

d1 = D(sin(t)*t)
d2 = D(sin(t)*cos(t))
@test isequal(expand_derivatives(d1), simplify(t*cos(t)+sin(t)))
@test isequal(expand_derivatives(d2), simplify(cos(t)*cos(t)+(-sin(t))*sin(t)))

eqs = [σ*(y-x),
       x*(ρ-z)-y,
       x*y - β*z]
jac = Symbolics.jacobian(eqs, [x, y, z])
test_equal(jac[1,1], -1σ)
test_equal(jac[1,2], σ)
test_equal(jac[1,3], 0)
test_equal(jac[2,1],  ρ - z)
test_equal(jac[2,2], -1)
test_equal(jac[2,3], -1x)
test_equal(jac[3,1], y)
test_equal(jac[3,2], x)
test_equal(jac[3,3], -1β)

# issue #545
z = t + t^2
#test_equal(expand_derivatives(D(z)), 1 + t * 2)

z = t-2t
#test_equal(expand_derivatives(D(z)), -1)

# Variable dependence checking in differentiation
@variables a(t) b(a)
@test !isequal(D(b), 0)
@test isequal(expand_derivatives(D(t)), 1)
@test isequal(expand_derivatives(Dx(x)), 1)

@variables x(t) y(t) z(t)

@test isequal(expand_derivatives(D(x * y)), simplify(y*D(x) + x*D(y)))
@test isequal(expand_derivatives(D(x * y)), simplify(D(x)*y + x*D(y)))

@test isequal(expand_derivatives(D(2t)), 2)
@test isequal(expand_derivatives(D(2x)), 2D(x))
@test isequal(expand_derivatives(D(x^2)), simplify(2 * x * D(x)))

# n-ary * and +
# isequal(Symbolics.derivative(Term(*, [x, y, z*ρ]), 1), y*(z*ρ))
# isequal(Symbolics.derivative(Term(+, [x*y, y, z]), 1), 1)

@test iszero(expand_derivatives(D(42)))
@test all(iszero, Symbolics.gradient(42, [t, x, y, z]))
@test all(iszero, Symbolics.hessian(42, [t, x, y, z]))
@test isequal(Symbolics.jacobian([t, x, 42], [t, x]),
              Num[1  0
                  Differential(t)(x)           1
                  0  0])

# issue 252
@variables beta, alpha, delta
@variables x1, x2, x3

# expression
tmp = beta * (alpha * exp(x1) * x2 ^ (alpha - 1) + 1 - delta) / x3
# derivative w.r.t. x1 and x2
t1 = Symbolics.gradient(tmp, [x1, x2])
@test_nowarn Symbolics.gradient(t1[1], [beta])

@variables t k
@variables x(t)
D = Differential(k)
@test Symbolics.tosymbol(D(x).val) === Symbol("xˍk(t)")

using Symbolics
@variables t x(t)
∂ₜ = Differential(t)
∂ₓ = Differential(x)
L = .5 * ∂ₜ(x)^2 - .5 * x^2
@test isequal(expand_derivatives(∂ₓ(L)), -1 * x)
test_equal(expand_derivatives(Differential(x)(L) - ∂ₜ(Differential(∂ₜ(x))(L))), -1 * (∂ₜ(∂ₜ(x)) + x))
@test isequal(expand_derivatives(Differential(x)(L) - ∂ₜ(Differential(∂ₜ(x))(L))), (-1 * x) - ∂ₜ(∂ₜ(x)))

@variables x2(t)
@test isequal(expand_derivatives(Differential(x)(2 * x + x2 * x)), 2 + x2)

@variables x y
@variables u(..)
Dy = Differential(y)
Dx = Differential(x)
dxyu = Dx(Dy(u(x,y)))
@test isequal(expand_derivatives(dxyu), dxyu)
dxxu = Dx(Dx(u(x,y)))
@test isequal(expand_derivatives(dxxu), dxxu)

using Symbolics, LinearAlgebra, SparseArrays
using Test

canonequal(a, b) = isequal(simplify(a), simplify(b))

# Calculus
@variables t σ ρ β
@variables x y z
@test isequal(
    (Differential(z) * Differential(y) * Differential(x))(t),
    Differential(z)(Differential(y)(Differential(x)(t)))
)

@test canonequal(
                 Symbolics.derivative(sin(cos(x)), x),
                 -sin(x) * cos(cos(x))
                )

Symbolics.@register no_der(x)
@test canonequal(
                 Symbolics.derivative([sin(cos(x)), hypot(x, no_der(x))], x),
                 [
                  -sin(x) * cos(cos(x)),
                  x/hypot(x, no_der(x)) + no_der(x)*Differential(x)(no_der(x))/hypot(x, no_der(x))
                 ]
                )

Symbolics.@register intfun(x)::Int
@test Symbolics.symtype(intfun(x)) === Int

eqs = [σ*(y-x),
       x*(ρ-z)-y,
       x*y - β*z]

∂ = Symbolics.jacobian(eqs,[x,y,z])
for i in 1:3
    ∇ = Symbolics.gradient(eqs[i],[x,y,z])
    @test canonequal(∂[i,:],∇)
end

@test all(canonequal.(Symbolics.gradient(eqs[1],[x,y,z]),[σ * -1,σ,0]))
@test all(canonequal.(Symbolics.hessian(eqs[1],[x,y,z]),0))

du = [x^2, y^3, x^4, sin(y), x+y, x+z^2, z+x, x+y^2+sin(z)]
reference_jac = sparse(Symbolics.jacobian(du, [x,y,z]))

@test findnz(Symbolics.jacobian_sparsity(du, [x,y,z]))[[1,2]] == findnz(reference_jac)[[1,2]]

let
    @variables t x(t) y(t) z(t)
    @test Symbolics.exprs_occur_in([x,y,z], x^2*y) == [true, true, false]
end

@test isequal(Symbolics.sparsejacobian(du, [x,y,z]), reference_jac)

using Symbolics

rosenbrock(X) = sum(1:length(X)-1) do i
    100 * (X[i+1] - X[i]^2)^2 + (1 - X[i])^2
end

@variables a,b
X = [a,b]

spoly(x) = simplify(x, expand=true)
rr = rosenbrock(X)

reference_hes = Symbolics.hessian(rr, X)
@test findnz(sparse(reference_hes))[1:2] == findnz(Symbolics.hessian_sparsity(rr, X))[1:2]

sp_hess = Symbolics.sparsehessian(rr, X)
@test findnz(sparse(reference_hes))[1:2] == findnz(sp_hess)[1:2]
@test isequal(map(spoly, findnz(sparse(reference_hes))[3]), map(spoly, findnz(sp_hess)[3]))

#96
@variables t x[1:4](t) ẋ[1:4](t)
expression = sin(x[1] + x[2] + x[3] + x[4]) |> Differential(t) |> expand_derivatives
expression2 = substitute(expression, Dict(Differential(t).(x) .=> ẋ))
@test isequal(expression2, (ẋ[1] + ẋ[2] + ẋ[3] + ẋ[4])*cos(x[1] + x[2] + x[3] + x[4]))

@test isequal(
    Symbolics.derivative(IfElse.ifelse(signbit(b), b^2, sqrt(b)), b),
    IfElse.ifelse(signbit(b), 2b, (1//2)*(sqrt(b)^-1))
)


text:
using WGLMakie, JSServe
WGLMakie.activate!()
open("dashboard.html", "w") do io
    println(io, """
        <div>
    """)
    show(io, MIME"text/html"(), Page(exportable=true, offline=true))
    show(io, MIME"text/html"(), scatter(1:4))
    show(io, MIME"text/html"(), surface(rand(4, 4)))
    # or anything else from JSServe, or that can be displayed as html:
    show(io, MIME"text/html"(), JSServe.Slider(1:3))
    println(io, """
        </div>
    """)
end

max_stars_repo_name: MisterBiggs/BeautifulMakie

max_issues_repo_name: MisterBiggs/BeautifulMakie

max_forks_repo_name: MisterBiggs/BeautifulMakie


text:
using RoME
using Base: Test

@testset "Basic Pose2 initialization" begin
  fg = initfg()
  initFactorGraph!(fg, lbl=:x0, ready=0)
  @test true

  N = 100
  fg = initfg()
  initFactorGraph!(fg, init=zeros(3), P0=0.1*eye(3), N=N, lbl=:x0, ready=0,   firstPoseType=Pose2)
  @test true
end

# test Pose3 initialization
@testset "Base Pose3 initialization" begin
  N = 100
  fg = initfg()
  initCov = eye(6)
  [initCov[i,i] = 0.01^2 for i in 4:6];
  initFactorGraph!(fg, P0=initCov, init=zeros(6), N=N, lbl=:x0, ready=0,   firstPoseType=Pose3)
  @test true
end

#


text:
# Maake "text/pg" translaations from Markdown

## use \( \) and \[ \] for  LaTeX
## use ``literal`` (and not `literal`)  for literal markup

"""
    show(io, ::MIME"text.pg", md::Markdown.MD)

Show *modified* markdown code in format suitable for a `pg` file.

There are necessary modifications due to how `Markdown` parses entities and how `pg` files are parsed.
As such, only *most* markdown features are available. Here are some differences:

* use "\`\`, \`\`" pairs for *literal* text. (In Markdown this indicates latex)
* use "\\(, \\)" pairs for *inline* latex and  "\\[,\\]" pairs for equation display latex
* Use `{{:a1}}`, …, `{{:a6}}` as placeholders for randomized parameters
* Parsing `\`\` 5*6*7 \`\`` will be fine, it is read as LaTeX by Markdown, but `\\( 5*6*7 \\)` will be a problem, as
  `*6*` will be parsed as italicized. Work around this with `⋅` (`\\cdot[tab]`), say.

Example

```
q = raw\"\"\"

Plain, **bold**, *italics*, ``literal``

----

* itemized
* lists

----

‵‵‵
code
blocks
(use triple back ticks)
‵‵‵

----

[link](https://webwork.maa.org/)

![image](https://avatars0.githubusercontent.com/u/1289488?s=280&v=4)

----

inline math: \\( x = \\sin(z)^2 \\)

Display math
\\[
y = \\frac{\\sin(x) - x + \\frac{x^3}{6}}{x^3}
\\]
\"\"\"
Page("Example formatting", (label(q),))
```

"""
function Base.show(io::IO, M::MIME"text/pg", md::Markdown.MD)
    for m in  md.content
        show(io,  M, m)
    end
end

function Base.show(io::IO, mime::MIME"text/pg", header::Markdown.Header{l}) where {l}
    txt = join(header.text)
    if l == 1
        println(io, "\n\$PAR\n\$BBOLD $(txt) \$EBOLD\n\$PAR\n\$PAR")
    end
    if l == 2
        println(io, "\n\$PAR\n\$BITALICS $(txt) \$EITALICS\n\$PAR")
    end
    if l > 2
        print(io, "\n\$PAR\n§ $(txt)\n\$PAR")
    end
end

function Base.show(io::IO, ::MIME"text/pg", md::Markdown.Paragraph)
    println(io, "\$PAR")
    for md in md.content
      show(io, "text/pg", md)
    end
end

function Base.show(io::IO, ::MIME"text/pg", md::Markdown.BlockQuote)
    println(io,  "\$BEGIN_ONE_COLUMN")
    for item in md.content
        show(io, "text/pg", item)
    end
    println(io,  "\$END_ONE_COLUMN")
end

function Base.show(io::IO, ::MIME"text/pg", md::Markdown.Code)
    println(io, "\n\$PAR")
    for l  in  split(md.code, "\n")
        # within  "\verb~" ~ \$var is not  needed, only $
        lr = replace(l, "\\\$"=> "\$")
        println(io, "⋮\\(\\verb~ $lr ~\\) \$BR")
    end
end

function Base.show(io::IO, M::MIME"text/pg", md::Markdown.List)
    itemized =  md.ordered >=  0
    for (i,  item) in enumerate(md.items)
        if itemized
            print(io, "\$BR $i) ")
        else
            print(io,  "\$BR • ")
        end
        for  i in  item
            if isa(i, Markdown.Paragraph) # avoid $PARR
                for  j in  i.content
                    show(io, M, j)
                end
            else
                show(io, M, i)
            end
        end
    end
end

function Base.show(io::IO, ::MIME"text/pg", md::Markdown.HorizontalRule)
    println(io, "\$HR")
end

function Base.show(io::IO, ::MIME"text/pg", md::Markdown.Bold)
    print(io, "\$BBOLD $(join(md.text)) \$EBOLD")
end

function Base.show(io::IO, ::MIME"text/pg", md::Markdown.Italic)
    print(io, "\$BITALIC $(join(md.text)) \$EITALIC")
end

#  use popup here; why?  why not?
function Base.show(io::IO, ::MIME"text/pg", md::Markdown.Image)
    id =  randstring('a':'z',10)
    url = match(r"^data:image/gif", md.url) == nothing ? md.url : "Image goes here"
    println(io, """

END_TEXT
\$$id = MODES(
HTML=>'

$(md.alt)

',
TeX=>'[$(md.alt)]($url)',
);
BEGIN_TEXT
\$$id
""")

end
#function Base.show(io::IO, ::MIME"text/pg", md::Markdown.Image)
#    println(io, """
#\\{ htmlLink( "javascript:windowpopup('$(md.url)');", '$(md.alt)' ) \\}
#""")
#end

function Base.show(io::IO, ::MIME"text/pg", md::Markdown.Link)
    buf = IOBuffer()
    for m  in md.text # an array!
        print(buf, m)
    end
    text = String(take!(buf))
    println(io, """
\\{ htmlLink( "javascript:windowpopup('$(md.url)');", '$(text)' ) \\}
""")
end

## Hack. We use  ``x`` for literals
function Base.show(io::IO, ::MIME"text/pg", md::Markdown.LaTeX)
    txt = md.formula
    txt = replace(txt, "\\"=>"")
    print(io, "\\(\\verb~$(txt)~\\)")
end

function Base.show(io::IO, ::MIME"text/pg", md::T) where {T <: AbstractString}
    print(io, md)
end

Base.show(io::IO, M::MIME"text/pg",  x::Symbol) = show(io, M,  string(x))


text:
println("Testing Unscented Kalman Filter...")

Δt = 0.1 # Set the time step

#Set the process function
function processFunction(x::Vector, Δt::Float64=0.1, μ::Float64=0.3)
    x1 = zeros(x)
    x1[1] = x[1] + Δt * -x[2]
    x1[2] = x[2] + Δt * (-μ * (1 - x[1]^2) * x[2] + x[1])
    x1
end

#Set the observation function.
observationFunction(x::Vector) = x

#Set process noise covariance matrix
processCovariance = 1e-2*[0.1 0;
    0 1e-3]

#Set the observation noise covariance
observationCovariance = 1e-1*eye(2)

#Create additive noise UKF model
ukfStateModel = NonlinearGaussianSSM(processFunction, processCovariance,
observationFunction, observationCovariance)
#End Section: Set the Unscented Kalman Filter Parameters
################################################################################

################################################################################
#Section: Generate noisy observations
#-------------------------------------------------------------------------------
#Set the true initial state of the oscillator
trueInitialState = [1.4, 0.0]

#Set the number of observations and generate the true values and the noisy
#observations.
numObs = 200
trueState = zeros(2,numObs)
noisyObs = zeros(2,numObs)
trueState[:,1] = trueInitialState
noisyObs[:,1] = trueInitialState + sqrt(observationCovariance)*randn(2)
for i in 2:numObs
    trueState[:,i] = processFunction(trueState[:,i-1])
    noisyObs[:,i] = trueState[:,i] + sqrt(observationCovariance)*randn(2)
end
#End Section: Generate noisy observations
################################################################################

################################################################################
#Section: Set guess of initial state
#-------------------------------------------------------------------------------
initial_guess = MvNormal([0.0,5.0], 5.0*eye(2))
#End Section: Set guess of initial state
################################################################################

################################################################################
#Section: Execute the Additive noise Unscented Kalman Filter
#-------------------------------------------------------------------------------
filtered_state = filter(ukfStateModel, noisyObs, initial_guess)
#End Section: Execute the Additive noise Unscented Kalman Filter
################################################################################

println("Unscented Kalman Filter passed.\n")


text:
struct TransposeHandler end

gethandler(broadcasted, ::Type{typeof(permutedims)}, ::Type{<:SBitstreamLike}) =
    !broadcasted ? TransposeHandler() :
                   error("Cannot generate hardware for broadcasted transpose (permutedims).")
init_state(::TransposeHandler) = (id = 0,)

function (handler::TransposeHandler)(buffer, netlist, state, inputs, outputs)
    # compute output size
    outsize = netsize(outputs[1])

    # add output net to netlist
    setsigned!(netlist, outputs[1], true)
    setreg!(netlist, outputs[1])

    write(buffer, """
        $stdcomment
        // BEGIN transpose$(state.id)
        $(state.id > 0 ? "" : "integer i, j;")
        always @(*) begin
            for (i = 0; i < $(outsize[2]); i = i + 1) begin
                for (j = 0; j < $(outsize[1]); j = j + 1) begin
                    $(name(outputs[1]))_p[(j*$(outsize[2])) + i] <= $(name(inputs[1]))_p[(i*$(outsize[1])) + j];
                    $(name(outputs[1]))_m[(j*$(outsize[2])) + i] <= $(name(inputs[1]))_m[(i*$(outsize[1])) + j];
                end
            end
        end
        // END transpose$(state.id)
        \n""")

    return buffer, (id = state.id + 1,)
end


text:
########### start optimization functions
function CoordDescentOpt(source_series::Vector{Float64}, target_series::Vector{Float64},
                                            shadowmat_dict::Dict, distmat_dict::Dict,
                                            E_vals::AbstractVector{Int}, tau_s_vals::AbstractVector{Int}, tau_p_vals::AbstractVector{Int};
                                            libsizemin::Int=0, libsizemax::Int=0,
                                            npred::Int=0, pred_start::Int=0,
                                            nreps = 5, nboots=0)

    bestres=Dict()
    count = 0
    for xx in 1:nreps
        res12, evalcount = _CoordDescentOpt(source_series, target_series,
                                                                    shadowmat_dict, distmat_dict,
                                                                    E_vals, tau_s_vals, tau_p_vals;
                                                                    libsizemin=libsizemin, libsizemax=libsizemax,
                                                                    npred=npred, pred_start=pred_start,
                                                                    nboots=nboots)
        count += evalcount
        if xx == 1
            bestres = res12
        elseif res12["rho"] > bestres["rho"]
            bestres = res12
        end
    end
    println("Finished $(count) CCM evaluations")
    return bestres
end

function _CoordDescentOpt(source_series::Vector{Float64}, target_series::Vector{Float64},
                                                shadowmat_dict::Dict, distmat_dict::Dict,
                                                E_vals::AbstractVector{Int}, tau_s_vals::AbstractVector{Int}, tau_p_vals::AbstractVector{Int};
                                                libsizemin::Int=0, libsizemax::Int=0,
                                                npred::Int=0, pred_start::Int=0,
                                                nboots=0)

    E_vals = convert(Vector{Int}, E_vals)
    tau_s_vals = convert(Vector{Int}, tau_s_vals)
    tau_p_vals = convert(Vector{Int}, tau_p_vals)

    toopt = ["E"; "tau_s"; "tau_p"]

    current_vals = {"E"=>E_vals[1], "tau_s"=> tau_s_vals[1], "tau_p"=>tau_p_vals[1]}
    librange, res12 = calcCCM(source_series, target_series,
                                                shadowmat_dict, distmat_dict,
                                                current_vals["E"], current_vals["tau_s"], current_vals["tau_p"];
                                                libsizemin=libsizemin, libsizemax=libsizemax,
                                                npred=npred, pred_start=pred_start,
                                                quick=true, nboots=nboots)

    rhoinit = getrho(res12)
    best_vals = merge(current_vals, ["rho"=>rhoinit])

    all_vals = ["E"=>E_vals, "tau_s"=>tau_s_vals, "tau_p"=>tau_p_vals]

    iternum = 1
    count = 0
    while true
        var_count = 0
        println("========Starting iteration $iternum===========")
        for var in shuffle(toopt)
            nochange_bool, evalcount = optvar(source_series, target_series, shadowmat_dict, distmat_dict,
                                                                    all_vals, current_vals, best_vals, var, libsizemax, npred, pred_start; nboots=nboots)
            count += evalcount
            current_vals[var] = best_vals[var][1] # make sure optimization of next variable is done with best value of this one

            if nochange_bool
                var_count += 1
            end
        end

        if var_count == size(toopt, 1)  # check for convergence (all variables unchanged)
            break
        end
        iternum += 1
    end
    return best_vals, count
end

function optvar(source_series::AbstractVector, target_series::AbstractVector, shadowmat_dict::Dict,
    distmat_dict::Dict, all_vals::Dict, current_vals::Dict,
    best_vals::Dict, var::ASCIIString, libsizemax::Int, npred::Int, pred_start::Int; nlag::Int=10, b_offset=1, nboots=0)

    if length(all_vals[var]) < 2
        return true, 0
    end
    count::Int= 0
    looplist     = shuffle(setdiff(all_vals[var], current_vals[var]))
    val_count::Int    = 0
    update_count::Int = 0
    for val in looplist
        current_vals[var] = val # update variable of interest
        libsizemax = min(libsizemax, calclibsizemax(length(source_series), current_vals["E"], current_vals["tau_s"], current_vals["tau_p"]))
        libsizemin = max(current_vals["E"] + b_offset + 1, libsizemax-nlag)
        librange, res12 = calcCCM(source_series, target_series,
                                                    shadowmat_dict, distmat_dict,
                                                    current_vals["E"],
                                                    current_vals["tau_s"], current_vals["tau_p"];
                                                    libsizemin=libsizemin, libsizemax=libsizemax,
                                                    npred=npred, pred_start=pred_start,
                                                    quick=true, nboots=nboots)
        rho = getrho(res12)
        if rho > best_vals["rho"] # update best value if you have an improvement
            best_vals[var] = val
            best_vals["rho"] = rho
            update_count += 1
        else
            val_count += 1
        end
        count += 1
    end

    if val_count + update_count !=length(looplist)
        error("Missing iteration in _optvar!!")
    end

    if val_count == size(all_vals[var],1)-1
        return true, count
    else
        return false, count
    end
end

function getrho(rhos::AbstractArray)
    rhos = rhos[!isnan(rhos)]
    if length(rhos) > 0
        rho = median(rhos)
    else
        rho = NaN
    end
    return rho
end
### end functions for CoordDescentOpt optimization


text:
## --- Malloc and free!

    p = malloc(100)
    @test isa(p, Ptr)
    @test free(p) == 0

    p = malloc(0x10)
    @test isa(p, Ptr)
    @test free(p) == 0

    p = malloc(Int16(100))
    @test isa(p, Ptr)
    @test free(p) == 0

    p = calloc(100*sizeof(Int64))
    @test isa(p, Ptr)
    @test MallocArray{Int64}(p, 10, 10) == fill(0,10,10)
    @test free(p) == 0

## --- memcpy, memcmp, etc.

    a = MallocArray{Float64}(undef, 100)
    @test memcpy!(a, ones(100)) == 0
    @test a == ones(100)

    @test memcmp(a, a, 100) === Int32(0)
    @test memcmp(c"foo", c"foo", 3) === Int32(0)
    @test memcmp(c"foo", "foo", 3) === Int32(0)
    @test memcmp(c"foo", c"bar", 3) != 0

    @test memset!(a, 0) === Int32(0)
    @test a == zeros(100)

    free(a)

## --- Other libc utility functions

    @test usleep(1000) === Int32(0)

    @test isa(StaticTools.time(), Int64)
    @test StaticTools.time() > 10^9


text:
using BenchmarkTools
using Revise
using Pkg
Pkg.activate(".")

using StaticKernels