text:
#==============================================================================#
# ACMPCA.jl
#
# This file is generated from:
# https://github.com/aws/aws-sdk-js/blob/master/apis/acm-pca-2017-08-22.normal.json
#==============================================================================#

__precompile__()

module ACMPCA

using AWSCore

"""
    using AWSSDK.ACMPCA.create_certificate_authority
    create_certificate_authority([::AWSConfig], arguments::Dict)
    create_certificate_authority([::AWSConfig]; CertificateAuthorityConfiguration=, CertificateAuthorityType=, <keyword arguments>)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "CreateCertificateAuthority", arguments::Dict)
    acm_pca([::AWSConfig], "CreateCertificateAuthority", CertificateAuthorityConfiguration=, CertificateAuthorityType=, <keyword arguments>)

# CreateCertificateAuthority Operation

Creates a private subordinate certificate authority (CA). You must specify the CA configuration, the revocation configuration, the CA type, and an optional idempotency token. The CA configuration specifies the name of the algorithm and key size to be used to create the CA private key, the type of signing algorithm that the CA uses to sign, and X.500 subject information. The CRL (certificate revocation list) configuration specifies the CRL expiration period in days (the validity period of the CRL), the Amazon S3 bucket that will contain the CRL, and a CNAME alias for the S3 bucket that is included in certificates issued by the CA. If successful, this operation returns the Amazon Resource Name (ARN) of the CA.

# Arguments

## `CertificateAuthorityConfiguration = [ ... ]` -- *Required*
Name and bit size of the private key algorithm, the name of the signing algorithm, and X.500 certificate subject information.
```
 CertificateAuthorityConfiguration = [
        "KeyAlgorithm" => <required> "RSA_2048", "RSA_4096", "EC_prime256v1" or "EC_secp384r1",
        "SigningAlgorithm" => <required> "SHA256WITHECDSA", "SHA384WITHECDSA", "SHA512WITHECDSA", "SHA256WITHRSA", "SHA384WITHRSA" or "SHA512WITHRSA",
        "Subject" => <required> [
            "Country" =>  ::String,
            "Organization" =>  ::String,
            "OrganizationalUnit" =>  ::String,
            "DistinguishedNameQualifier" =>  ::String,
            "State" =>  ::String,
            "CommonName" =>  ::String,
            "SerialNumber" =>  ::String,
            "Locality" =>  ::String,
            "Title" =>  ::String,
            "Surname" =>  ::String,
            "GivenName" =>  ::String,
            "Initials" =>  ::String,
            "Pseudonym" =>  ::String,
            "GenerationQualifier" =>  ::String
        ]
    ]
```

## `RevocationConfiguration = ["CrlConfiguration" =>  [ ... ]]`
Contains a Boolean value that you can use to enable a certification revocation list (CRL) for the CA, the name of the S3 bucket to which ACM PCA will write the CRL, and an optional CNAME alias that you can use to hide the name of your bucket in the **CRL Distribution Points** extension of your CA certificate. For more information, see the [CrlConfiguration](@ref) structure.
```
 RevocationConfiguration = ["CrlConfiguration" =>  [
            "Enabled" => <required> ::Bool,
            "ExpirationInDays" =>  ::Int,
            "CustomCname" =>  ::String,
            "S3BucketName" =>  ::String
        ]]
```

## `CertificateAuthorityType = "SUBORDINATE"` -- *Required*
The type of the certificate authority. Currently, this must be **SUBORDINATE**.

## `IdempotencyToken = ::String`
Alphanumeric string that can be used to distinguish between calls to **CreateCertificateAuthority**. Idempotency tokens time out after five minutes. Therefore, if you call **CreateCertificateAuthority** multiple times with the same idempotency token within a five minute period, ACM PCA recognizes that you are requesting only one certificate. As a result, ACM PCA issues only one. If you change the idempotency token for each call, however, ACM PCA recognizes that you are requesting multiple certificates.

# Returns

`CreateCertificateAuthorityResponse`

# Exceptions

`InvalidArgsException`, `InvalidPolicyException` or `LimitExceededException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/CreateCertificateAuthority)
"""
@inline create_certificate_authority(aws::AWSConfig=default_aws_config(); args...) = create_certificate_authority(aws, args)

@inline create_certificate_authority(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "CreateCertificateAuthority", args)

@inline create_certificate_authority(args) = create_certificate_authority(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.create_certificate_authority_audit_report
    create_certificate_authority_audit_report([::AWSConfig], arguments::Dict)
    create_certificate_authority_audit_report([::AWSConfig]; CertificateAuthorityArn=, S3BucketName=, AuditReportResponseFormat=)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "CreateCertificateAuthorityAuditReport", arguments::Dict)
    acm_pca([::AWSConfig], "CreateCertificateAuthorityAuditReport", CertificateAuthorityArn=, S3BucketName=, AuditReportResponseFormat=)

# CreateCertificateAuthorityAuditReport Operation

Creates an audit report that lists every time that the your CA private key is used. The report is saved in the Amazon S3 bucket that you specify on input. The [IssueCertificate](@ref) and [RevokeCertificate](@ref) operations use the private key. You can generate a new report every 30 minutes.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
Amazon Resource Name (ARN) of the CA to be audited. This is of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*` .

## `S3BucketName = ::String` -- *Required*
Name of the S3 bucket that will contain the audit report.

## `AuditReportResponseFormat = "JSON" or "CSV"` -- *Required*
Format in which to create the report. This can be either **JSON** or **CSV**.

# Returns

`CreateCertificateAuthorityAuditReportResponse`

# Exceptions

`RequestInProgressException`, `RequestFailedException`, `ResourceNotFoundException`, `InvalidArnException`, `InvalidArgsException` or `InvalidStateException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/CreateCertificateAuthorityAuditReport)
"""
@inline create_certificate_authority_audit_report(aws::AWSConfig=default_aws_config(); args...) = create_certificate_authority_audit_report(aws, args)

@inline create_certificate_authority_audit_report(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "CreateCertificateAuthorityAuditReport", args)

@inline create_certificate_authority_audit_report(args) = create_certificate_authority_audit_report(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.delete_certificate_authority
    delete_certificate_authority([::AWSConfig], arguments::Dict)
    delete_certificate_authority([::AWSConfig]; CertificateAuthorityArn=, <keyword arguments>)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "DeleteCertificateAuthority", arguments::Dict)
    acm_pca([::AWSConfig], "DeleteCertificateAuthority", CertificateAuthorityArn=, <keyword arguments>)

# DeleteCertificateAuthority Operation

Deletes a private certificate authority (CA). You must provide the ARN (Amazon Resource Name) of the private CA that you want to delete. You can find the ARN by calling the [ListCertificateAuthorities](@ref) operation. Before you can delete a CA, you must disable it. Call the [UpdateCertificateAuthority](@ref) operation and set the **CertificateAuthorityStatus** parameter to `DISABLED`.

Additionally, you can delete a CA if you are waiting for it to be created (the **Status** field of the [CertificateAuthority](@ref) is `CREATING`). You can also delete it if the CA has been created but you haven't yet imported the signed certificate (the **Status** is `PENDING_CERTIFICATE`) into ACM PCA.

If the CA is in one of the aforementioned states and you call [DeleteCertificateAuthority](@ref), the CA's status changes to `DELETED`. However, the CA won't be permentantly deleted until the restoration period has passed. By default, if you do not set the `PermanentDeletionTimeInDays` parameter, the CA remains restorable for 30 days. You can set the parameter from 7 to 30 days. The [DescribeCertificateAuthority](@ref) operation returns the time remaining in the restoration window of a Private CA in the `DELETED` state. To restore an eligable CA, call the [RestoreCertificateAuthority](@ref) operation.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) that was returned when you called [CreateCertificateAuthority](@ref). This must have the following form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*` .

## `PermanentDeletionTimeInDays = ::Int`
The number of days to make a CA restorable after it has been deleted. This can be anywhere from 7 to 30 days, with 30 being the default.

# Exceptions

`ConcurrentModificationException`, `ResourceNotFoundException`, `InvalidArnException` or `InvalidStateException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/DeleteCertificateAuthority)
"""
@inline delete_certificate_authority(aws::AWSConfig=default_aws_config(); args...) = delete_certificate_authority(aws, args)

@inline delete_certificate_authority(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "DeleteCertificateAuthority", args)

@inline delete_certificate_authority(args) = delete_certificate_authority(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.describe_certificate_authority
    describe_certificate_authority([::AWSConfig], arguments::Dict)
    describe_certificate_authority([::AWSConfig]; CertificateAuthorityArn=)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "DescribeCertificateAuthority", arguments::Dict)
    acm_pca([::AWSConfig], "DescribeCertificateAuthority", CertificateAuthorityArn=)

# DescribeCertificateAuthority Operation

Lists information about your private certificate authority (CA). You specify the private CA on input by its ARN (Amazon Resource Name). The output contains the status of your CA. This can be any of the following:

*   `CREATING` - ACM PCA is creating your private certificate authority.

*   `PENDING_CERTIFICATE` - The certificate is pending. You must use your on-premises root or subordinate CA to sign your private CA CSR and then import it into PCA.

*   `ACTIVE` - Your private CA is active.

*   `DISABLED` - Your private CA has been disabled.

*   `EXPIRED` - Your private CA certificate has expired.

*   `FAILED` - Your private CA has failed. Your CA can fail because of problems such a network outage or backend AWS failure or other errors. A failed CA can never return to the pending state. You must create a new CA.

*   `DELETED` - Your private CA is within the restoration period, after which it will be permanently deleted. The length of time remaining in the CA's restoration period will also be included in this operation's output.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) that was returned when you called [CreateCertificateAuthority](@ref). This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*` .

# Returns

`DescribeCertificateAuthorityResponse`

# Exceptions

`ResourceNotFoundException` or `InvalidArnException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/DescribeCertificateAuthority)
"""
@inline describe_certificate_authority(aws::AWSConfig=default_aws_config(); args...) = describe_certificate_authority(aws, args)

@inline describe_certificate_authority(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "DescribeCertificateAuthority", args)

@inline describe_certificate_authority(args) = describe_certificate_authority(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.describe_certificate_authority_audit_report
    describe_certificate_authority_audit_report([::AWSConfig], arguments::Dict)
    describe_certificate_authority_audit_report([::AWSConfig]; CertificateAuthorityArn=, AuditReportId=)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "DescribeCertificateAuthorityAuditReport", arguments::Dict)
    acm_pca([::AWSConfig], "DescribeCertificateAuthorityAuditReport", CertificateAuthorityArn=, AuditReportId=)

# DescribeCertificateAuthorityAuditReport Operation

Lists information about a specific audit report created by calling the [CreateCertificateAuthorityAuditReport](@ref) operation. Audit information is created every time the certificate authority (CA) private key is used. The private key is used when you call the [IssueCertificate](@ref) operation or the [RevokeCertificate](@ref) operation.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) of the private CA. This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*` .

## `AuditReportId = ::String` -- *Required*
The report ID returned by calling the [CreateCertificateAuthorityAuditReport](@ref) operation.

# Returns

`DescribeCertificateAuthorityAuditReportResponse`

# Exceptions

`ResourceNotFoundException`, `InvalidArnException` or `InvalidArgsException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/DescribeCertificateAuthorityAuditReport)
"""
@inline describe_certificate_authority_audit_report(aws::AWSConfig=default_aws_config(); args...) = describe_certificate_authority_audit_report(aws, args)

@inline describe_certificate_authority_audit_report(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "DescribeCertificateAuthorityAuditReport", args)

@inline describe_certificate_authority_audit_report(args) = describe_certificate_authority_audit_report(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.get_certificate
    get_certificate([::AWSConfig], arguments::Dict)
    get_certificate([::AWSConfig]; CertificateAuthorityArn=, CertificateArn=)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "GetCertificate", arguments::Dict)
    acm_pca([::AWSConfig], "GetCertificate", CertificateAuthorityArn=, CertificateArn=)

# GetCertificate Operation

Retrieves a certificate from your private CA. The ARN of the certificate is returned when you call the [IssueCertificate](@ref) operation. You must specify both the ARN of your private CA and the ARN of the issued certificate when calling the **GetCertificate** operation. You can retrieve the certificate if it is in the **ISSUED** state. You can call the [CreateCertificateAuthorityAuditReport](@ref) operation to create a report that contains information about all of the certificates issued and revoked by your private CA.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) that was returned when you called [CreateCertificateAuthority](@ref). This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*` .

## `CertificateArn = ::String` -- *Required*
The ARN of the issued certificate. The ARN contains the certificate serial number and must be in the following form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*/certificate/*286535153982981100925020015808220737245*`

# Returns

`GetCertificateResponse`

# Exceptions

`RequestInProgressException`, `RequestFailedException`, `ResourceNotFoundException`, `InvalidArnException` or `InvalidStateException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/GetCertificate)
"""
@inline get_certificate(aws::AWSConfig=default_aws_config(); args...) = get_certificate(aws, args)

@inline get_certificate(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "GetCertificate", args)

@inline get_certificate(args) = get_certificate(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.get_certificate_authority_certificate
    get_certificate_authority_certificate([::AWSConfig], arguments::Dict)
    get_certificate_authority_certificate([::AWSConfig]; CertificateAuthorityArn=)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "GetCertificateAuthorityCertificate", arguments::Dict)
    acm_pca([::AWSConfig], "GetCertificateAuthorityCertificate", CertificateAuthorityArn=)

# GetCertificateAuthorityCertificate Operation

Retrieves the certificate and certificate chain for your private certificate authority (CA). Both the certificate and the chain are base64 PEM-encoded. The chain does not include the CA certificate. Each certificate in the chain signs the one before it.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) of your private CA. This is of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*` .

# Returns

`GetCertificateAuthorityCertificateResponse`

# Exceptions

`ResourceNotFoundException`, `InvalidStateException` or `InvalidArnException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/GetCertificateAuthorityCertificate)
"""
@inline get_certificate_authority_certificate(aws::AWSConfig=default_aws_config(); args...) = get_certificate_authority_certificate(aws, args)

@inline get_certificate_authority_certificate(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "GetCertificateAuthorityCertificate", args)

@inline get_certificate_authority_certificate(args) = get_certificate_authority_certificate(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.get_certificate_authority_csr
    get_certificate_authority_csr([::AWSConfig], arguments::Dict)
    get_certificate_authority_csr([::AWSConfig]; CertificateAuthorityArn=)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "GetCertificateAuthorityCsr", arguments::Dict)
    acm_pca([::AWSConfig], "GetCertificateAuthorityCsr", CertificateAuthorityArn=)

# GetCertificateAuthorityCsr Operation

Retrieves the certificate signing request (CSR) for your private certificate authority (CA). The CSR is created when you call the [CreateCertificateAuthority](@ref) operation. Take the CSR to your on-premises X.509 infrastructure and sign it by using your root or a subordinate CA. Then import the signed certificate back into ACM PCA by calling the [ImportCertificateAuthorityCertificate](@ref) operation. The CSR is returned as a base64 PEM-encoded string.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) that was returned when you called the [CreateCertificateAuthority](@ref) operation. This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*`

# Returns

`GetCertificateAuthorityCsrResponse`

# Exceptions

`RequestInProgressException`, `RequestFailedException`, `ResourceNotFoundException`, `InvalidArnException` or `InvalidStateException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/GetCertificateAuthorityCsr)
"""
@inline get_certificate_authority_csr(aws::AWSConfig=default_aws_config(); args...) = get_certificate_authority_csr(aws, args)

@inline get_certificate_authority_csr(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "GetCertificateAuthorityCsr", args)

@inline get_certificate_authority_csr(args) = get_certificate_authority_csr(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.import_certificate_authority_certificate
    import_certificate_authority_certificate([::AWSConfig], arguments::Dict)
    import_certificate_authority_certificate([::AWSConfig]; CertificateAuthorityArn=, Certificate=, CertificateChain=)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "ImportCertificateAuthorityCertificate", arguments::Dict)
    acm_pca([::AWSConfig], "ImportCertificateAuthorityCertificate", CertificateAuthorityArn=, Certificate=, CertificateChain=)

# ImportCertificateAuthorityCertificate Operation

Imports your signed private CA certificate into ACM PCA. Before you can call this operation, you must create the private certificate authority by calling the [CreateCertificateAuthority](@ref) operation. You must then generate a certificate signing request (CSR) by calling the [GetCertificateAuthorityCsr](@ref) operation. Take the CSR to your on-premises CA and use the root certificate or a subordinate certificate to sign it. Create a certificate chain and copy the signed certificate and the certificate chain to your working directory.

**Note**
> Your certificate chain must not include the private CA certificate that you are importing.

**Note**
> Your on-premises CA certificate must be the last certificate in your chain. The subordinate certificate, if any, that your root CA signed must be next to last. The subordinate certificate signed by the preceding subordinate CA must come next, and so on until your chain is built.

**Note**
> The chain must be PEM-encoded.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) that was returned when you called [CreateCertificateAuthority](@ref). This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*`

## `Certificate = blob` -- *Required*
The PEM-encoded certificate for your private CA. This must be signed by using your on-premises CA.

## `CertificateChain = blob` -- *Required*
A PEM-encoded file that contains all of your certificates, other than the certificate you're importing, chaining up to your root CA. Your on-premises root certificate is the last in the chain, and each certificate in the chain signs the one preceding.

# Exceptions

`ConcurrentModificationException`, `RequestInProgressException`, `RequestFailedException`, `ResourceNotFoundException`, `InvalidArnException`, `InvalidStateException`, `MalformedCertificateException` or `CertificateMismatchException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/ImportCertificateAuthorityCertificate)
"""
@inline import_certificate_authority_certificate(aws::AWSConfig=default_aws_config(); args...) = import_certificate_authority_certificate(aws, args)

@inline import_certificate_authority_certificate(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "ImportCertificateAuthorityCertificate", args)

@inline import_certificate_authority_certificate(args) = import_certificate_authority_certificate(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.issue_certificate
    issue_certificate([::AWSConfig], arguments::Dict)
    issue_certificate([::AWSConfig]; CertificateAuthorityArn=, Csr=, SigningAlgorithm=, Validity=, <keyword arguments>)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "IssueCertificate", arguments::Dict)
    acm_pca([::AWSConfig], "IssueCertificate", CertificateAuthorityArn=, Csr=, SigningAlgorithm=, Validity=, <keyword arguments>)

# IssueCertificate Operation

Uses your private certificate authority (CA) to issue a client certificate. This operation returns the Amazon Resource Name (ARN) of the certificate. You can retrieve the certificate by calling the [GetCertificate](@ref) operation and specifying the ARN.

**Note**
> You cannot use the ACM **ListCertificateAuthorities** operation to retrieve the ARNs of the certificates that you issue by using ACM PCA.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) that was returned when you called [CreateCertificateAuthority](@ref). This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*`

## `Csr = blob` -- *Required*
The certificate signing request (CSR) for the certificate you want to issue. You can use the following OpenSSL command to create the CSR and a 2048 bit RSA private key.

`openssl req -new -newkey rsa:2048 -days 365 -keyout private/test_cert_priv_key.pem -out csr/test_cert_.csr`

If you have a configuration file, you can use the following OpenSSL command. The `usr_cert` block in the configuration file contains your X509 version 3 extensions.

`openssl req -new -config openssl_rsa.cnf -extensions usr_cert -newkey rsa:2048 -days -365 -keyout private/test_cert_priv_key.pem -out csr/test_cert_.csr`

## `SigningAlgorithm = "SHA256WITHECDSA", "SHA384WITHECDSA", "SHA512WITHECDSA", "SHA256WITHRSA", "SHA384WITHRSA" or "SHA512WITHRSA"` -- *Required*
The name of the algorithm that will be used to sign the certificate to be issued.

## `Validity = [ ... ]` -- *Required*
The type of the validity period.
```
 Validity = [
        "Value" => <required> ::Int,
        "Type" => <required> "END_DATE", "ABSOLUTE", "DAYS", "MONTHS" or "YEARS"
    ]
```

## `IdempotencyToken = ::String`
Custom string that can be used to distinguish between calls to the **IssueCertificate** operation. Idempotency tokens time out after one hour. Therefore, if you call **IssueCertificate** multiple times with the same idempotency token within 5 minutes, ACM PCA recognizes that you are requesting only one certificate and will issue only one. If you change the idempotency token for each call, PCA recognizes that you are requesting multiple certificates.

# Returns

`IssueCertificateResponse`

# Exceptions

`LimitExceededException`, `ResourceNotFoundException`, `InvalidStateException`, `InvalidArnException`, `InvalidArgsException` or `MalformedCSRException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/IssueCertificate)
"""
@inline issue_certificate(aws::AWSConfig=default_aws_config(); args...) = issue_certificate(aws, args)

@inline issue_certificate(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "IssueCertificate", args)

@inline issue_certificate(args) = issue_certificate(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.list_certificate_authorities
    list_certificate_authorities([::AWSConfig], arguments::Dict)
    list_certificate_authorities([::AWSConfig]; <keyword arguments>)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "ListCertificateAuthorities", arguments::Dict)
    acm_pca([::AWSConfig], "ListCertificateAuthorities", <keyword arguments>)

# ListCertificateAuthorities Operation

Lists the private certificate authorities that you created by using the [CreateCertificateAuthority](@ref) operation.

# Arguments

## `NextToken = ::String`
Use this parameter when paginating results in a subsequent request after you receive a response with truncated results. Set it to the value of the `NextToken` parameter from the response you just received.

## `MaxResults = ::Int`
Use this parameter when paginating results to specify the maximum number of items to return in the response on each page. If additional items exist beyond the number you specify, the `NextToken` element is sent in the response. Use this `NextToken` value in a subsequent request to retrieve additional items.

# Returns

`ListCertificateAuthoritiesResponse`

# Exceptions

`InvalidNextTokenException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/ListCertificateAuthorities)
"""
@inline list_certificate_authorities(aws::AWSConfig=default_aws_config(); args...) = list_certificate_authorities(aws, args)

@inline list_certificate_authorities(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "ListCertificateAuthorities", args)

@inline list_certificate_authorities(args) = list_certificate_authorities(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.list_tags
    list_tags([::AWSConfig], arguments::Dict)
    list_tags([::AWSConfig]; CertificateAuthorityArn=, <keyword arguments>)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "ListTags", arguments::Dict)
    acm_pca([::AWSConfig], "ListTags", CertificateAuthorityArn=, <keyword arguments>)

# ListTags Operation

Lists the tags, if any, that are associated with your private CA. Tags are labels that you can use to identify and organize your CAs. Each tag consists of a key and an optional value. Call the [TagCertificateAuthority](@ref) operation to add one or more tags to your CA. Call the [UntagCertificateAuthority](@ref) operation to remove tags.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) that was returned when you called the [CreateCertificateAuthority](@ref) operation. This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*`

## `NextToken = ::String`
Use this parameter when paginating results in a subsequent request after you receive a response with truncated results. Set it to the value of **NextToken** from the response you just received.

## `MaxResults = ::Int`
Use this parameter when paginating results to specify the maximum number of items to return in the response. If additional items exist beyond the number you specify, the **NextToken** element is sent in the response. Use this **NextToken** value in a subsequent request to retrieve additional items.

# Returns

`ListTagsResponse`

# Exceptions

`ResourceNotFoundException` or `InvalidArnException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/ListTags)
"""
@inline list_tags(aws::AWSConfig=default_aws_config(); args...) = list_tags(aws, args)

@inline list_tags(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "ListTags", args)

@inline list_tags(args) = list_tags(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.restore_certificate_authority
    restore_certificate_authority([::AWSConfig], arguments::Dict)
    restore_certificate_authority([::AWSConfig]; CertificateAuthorityArn=)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "RestoreCertificateAuthority", arguments::Dict)
    acm_pca([::AWSConfig], "RestoreCertificateAuthority", CertificateAuthorityArn=)

# RestoreCertificateAuthority Operation

Restores a certificate authority (CA) that is in the `DELETED` state. You can restore a CA during the period that you defined in the **PermanentDeletionTimeInDays** parameter of the [DeleteCertificateAuthority](@ref) operation. Currently, you can specify 7 to 30 days. If you did not specify a **PermanentDeletionTimeInDays** value, by default you can restore the CA at any time in a 30 day period. You can check the time remaining in the restoration period of a private CA in the `DELETED` state by calling the [DescribeCertificateAuthority](@ref) or [ListCertificateAuthorities](@ref) operations. The status of a restored CA is set to its pre-deletion status when the **RestoreCertificateAuthority** operation returns. To change its status to `ACTIVE`, call the [UpdateCertificateAuthority](@ref) operation. If the private CA was in the `PENDING_CERTIFICATE` state at deletion, you must use the [ImportCertificateAuthorityCertificate](@ref) operation to import a certificate authority into the private CA before it can be activated. You cannot restore a CA after the restoration period has ended.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) that was returned when you called the [CreateCertificateAuthority](@ref) operation. This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*`

# Exceptions

`ResourceNotFoundException`, `InvalidStateException` or `InvalidArnException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/RestoreCertificateAuthority)
"""
@inline restore_certificate_authority(aws::AWSConfig=default_aws_config(); args...) = restore_certificate_authority(aws, args)

@inline restore_certificate_authority(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "RestoreCertificateAuthority", args)

@inline restore_certificate_authority(args) = restore_certificate_authority(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.revoke_certificate
    revoke_certificate([::AWSConfig], arguments::Dict)
    revoke_certificate([::AWSConfig]; CertificateAuthorityArn=, CertificateSerial=, RevocationReason=)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "RevokeCertificate", arguments::Dict)
    acm_pca([::AWSConfig], "RevokeCertificate", CertificateAuthorityArn=, CertificateSerial=, RevocationReason=)

# RevokeCertificate Operation

Revokes a certificate that you issued by calling the [IssueCertificate](@ref) operation. If you enable a certificate revocation list (CRL) when you create or update your private CA, information about the revoked certificates will be included in the CRL. ACM PCA writes the CRL to an S3 bucket that you specify. For more information about revocation, see the [CrlConfiguration](@ref) structure. ACM PCA also writes revocation information to the audit report. For more information, see [CreateCertificateAuthorityAuditReport](@ref).

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
Amazon Resource Name (ARN) of the private CA that issued the certificate to be revoked. This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*`

## `CertificateSerial = ::String` -- *Required*
Serial number of the certificate to be revoked. This must be in hexadecimal format. You can retrieve the serial number by calling [GetCertificate](@ref) with the Amazon Resource Name (ARN) of the certificate you want and the ARN of your private CA. The **GetCertificate** operation retrieves the certificate in the PEM format. You can use the following OpenSSL command to list the certificate in text format and copy the hexadecimal serial number.

`openssl x509 -in *file_path* -text -noout`

You can also copy the serial number from the console or use the [DescribeCertificate](https://docs.aws.amazon.com/acm/latest/APIReference/API_DescribeCertificate.html) operation in the *AWS Certificate Manager API Reference*.

## `RevocationReason = "UNSPECIFIED", "KEY_COMPROMISE", "CERTIFICATE_AUTHORITY_COMPROMISE", "AFFILIATION_CHANGED", "SUPERSEDED", "CESSATION_OF_OPERATION", "PRIVILEGE_WITHDRAWN" or "A_A_COMPROMISE"` -- *Required*
Specifies why you revoked the certificate.

# Exceptions

`ConcurrentModificationException`, `InvalidArnException`, `InvalidStateException`, `ResourceNotFoundException`, `RequestAlreadyProcessedException`, `RequestInProgressException` or `RequestFailedException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/RevokeCertificate)
"""
@inline revoke_certificate(aws::AWSConfig=default_aws_config(); args...) = revoke_certificate(aws, args)

@inline revoke_certificate(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "RevokeCertificate", args)

@inline revoke_certificate(args) = revoke_certificate(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.tag_certificate_authority
    tag_certificate_authority([::AWSConfig], arguments::Dict)
    tag_certificate_authority([::AWSConfig]; CertificateAuthorityArn=, Tags=)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "TagCertificateAuthority", arguments::Dict)
    acm_pca([::AWSConfig], "TagCertificateAuthority", CertificateAuthorityArn=, Tags=)

# TagCertificateAuthority Operation

Adds one or more tags to your private CA. Tags are labels that you can use to identify and organize your AWS resources. Each tag consists of a key and an optional value. You specify the private CA on input by its Amazon Resource Name (ARN). You specify the tag by using a key-value pair. You can apply a tag to just one private CA if you want to identify a specific characteristic of that CA, or you can apply the same tag to multiple private CAs if you want to filter for a common relationship among those CAs. To remove one or more tags, use the [UntagCertificateAuthority](@ref) operation. Call the [ListTags](@ref) operation to see what tags are associated with your CA.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) that was returned when you called [CreateCertificateAuthority](@ref). This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*`

## `Tags = [[ ... ], ...]` -- *Required*
List of tags to be associated with the CA.
```
 Tags = [[
        "Key" => <required> ::String,
        "Value" =>  ::String
    ], ...]
```

# Exceptions

`ResourceNotFoundException`, `InvalidArnException`, `InvalidStateException`, `InvalidTagException` or `TooManyTagsException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/TagCertificateAuthority)
"""
@inline tag_certificate_authority(aws::AWSConfig=default_aws_config(); args...) = tag_certificate_authority(aws, args)

@inline tag_certificate_authority(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "TagCertificateAuthority", args)

@inline tag_certificate_authority(args) = tag_certificate_authority(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.untag_certificate_authority
    untag_certificate_authority([::AWSConfig], arguments::Dict)
    untag_certificate_authority([::AWSConfig]; CertificateAuthorityArn=, Tags=)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "UntagCertificateAuthority", arguments::Dict)
    acm_pca([::AWSConfig], "UntagCertificateAuthority", CertificateAuthorityArn=, Tags=)

# UntagCertificateAuthority Operation

Remove one or more tags from your private CA. A tag consists of a key-value pair. If you do not specify the value portion of the tag when calling this operation, the tag will be removed regardless of value. If you specify a value, the tag is removed only if it is associated with the specified value. To add tags to a private CA, use the [TagCertificateAuthority](@ref). Call the [ListTags](@ref) operation to see what tags are associated with your CA.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
The Amazon Resource Name (ARN) that was returned when you called [CreateCertificateAuthority](@ref). This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*`

## `Tags = [[ ... ], ...]` -- *Required*
List of tags to be removed from the CA.
```
 Tags = [[
        "Key" => <required> ::String,
        "Value" =>  ::String
    ], ...]
```

# Exceptions

`ResourceNotFoundException`, `InvalidArnException`, `InvalidStateException` or `InvalidTagException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/UntagCertificateAuthority)
"""
@inline untag_certificate_authority(aws::AWSConfig=default_aws_config(); args...) = untag_certificate_authority(aws, args)

@inline untag_certificate_authority(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "UntagCertificateAuthority", args)

@inline untag_certificate_authority(args) = untag_certificate_authority(default_aws_config(), args)

"""
    using AWSSDK.ACMPCA.update_certificate_authority
    update_certificate_authority([::AWSConfig], arguments::Dict)
    update_certificate_authority([::AWSConfig]; CertificateAuthorityArn=, <keyword arguments>)

    using AWSCore.Services.acm_pca
    acm_pca([::AWSConfig], "UpdateCertificateAuthority", arguments::Dict)
    acm_pca([::AWSConfig], "UpdateCertificateAuthority", CertificateAuthorityArn=, <keyword arguments>)

# UpdateCertificateAuthority Operation

Updates the status or configuration of a private certificate authority (CA). Your private CA must be in the `ACTIVE` or `DISABLED` state before you can update it. You can disable a private CA that is in the `ACTIVE` state or make a CA that is in the `DISABLED` state active again.

# Arguments

## `CertificateAuthorityArn = ::String` -- *Required*
Amazon Resource Name (ARN) of the private CA that issued the certificate to be revoked. This must be of the form:

`arn:aws:acm-pca:*region*:*account*:certificate-authority/*12345678-1234-1234-1234-123456789012*`

## `RevocationConfiguration = ["CrlConfiguration" =>  [ ... ]]`
Revocation information for your private CA.
```
 RevocationConfiguration = ["CrlConfiguration" =>  [
            "Enabled" => <required> ::Bool,
            "ExpirationInDays" =>  ::Int,
            "CustomCname" =>  ::String,
            "S3BucketName" =>  ::String
        ]]
```

## `Status = "CREATING", "PENDING_CERTIFICATE", "ACTIVE", "DELETED", "DISABLED", "EXPIRED" or "FAILED"`
Status of your private CA.

# Exceptions

`ConcurrentModificationException`, `ResourceNotFoundException`, `InvalidArgsException`, `InvalidArnException`, `InvalidStateException` or `InvalidPolicyException`.

See also: [AWS API Documentation](https://docs.aws.amazon.com/goto/WebAPI/acm-pca-2017-08-22/UpdateCertificateAuthority)
"""
@inline update_certificate_authority(aws::AWSConfig=default_aws_config(); args...) = update_certificate_authority(aws, args)

@inline update_certificate_authority(aws::AWSConfig, args) = AWSCore.Services.acm_pca(aws, "UpdateCertificateAuthority", args)

@inline update_certificate_authority(args) = update_certificate_authority(default_aws_config(), args)

end # module ACMPCA

#==============================================================================#
# End of file
#==============================================================================#


text:
@testset "GC content" begin
    @test gc_content(dna"") === 0.0
    @test gc_content(dna"AATA") === 0.0
    @test gc_content(dna"ACGT") === 0.5
    @test gc_content(dna"CGGC") === 1.0
    @test gc_content(dna"ACATTGTGTATAACAAAAGG") === 6 / 20
    @test gc_content(dna"GAGGCGTTTATCATC"[2:end]) === 6 / 14

    @test gc_content(DNAKmer("AATA")) === 0.0
    @test gc_content(DNAKmer("ACGT")) === 0.5
    @test gc_content(DNAKmer("CGGC")) === 1.0
    @test gc_content(DNAKmer("ACATTGTGTATAACAAAAGG")) === 6 / 20

    @test gc_content(rna"") === 0.0
    @test gc_content(rna"AAUA") === 0.0
    @test gc_content(rna"ACGU") === 0.5
    @test gc_content(rna"CGGC") === 1.0
    @test gc_content(rna"ACAUUGUGUAUAACAAAAGG") === 6 / 20
    @test gc_content(rna"GAGGCGUUUAUCAUC"[2:end]) === 6 / 14

    @test gc_content(RNAKmer("AAUA")) === 0.0
    @test gc_content(RNAKmer("ACGU")) === 0.5
    @test gc_content(RNAKmer("CGGC")) === 1.0
    @test gc_content(RNAKmer("ACAUUGUGUAUAACAAAAGG")) === 6 / 20

    @test_throws Exception gc_content(aa"ARN")

    Random.seed!(1234)
    for _ in 1:200
        s = randdnaseq(rand(1:100))
        @test gc_content(s) === count(isGC, s) / length(s)
        @test gc_content(BioSequence{DNAAlphabet{2}}(s)) === count(isGC, s) / length(s)
        i = rand(1:lastindex(s))
        j = rand(i-1:lastindex(s))
        @test gc_content(s[i:j]) === (j < i ? 0.0 : count(isGC, s[i:j]) / (j - i + 1))
    end
end

ext: jl


text:
using PortfolioBedtest
using Test

@testset "PortfolioBedtest.jl" begin
    # Write your tests here.
end


text:
import POMDPs
# State space; not complete and no need to initiate

# Initial state distribution
# function POMDPs.initialstate_distribution(pomdp::FireWorld)
function POMDPs.initialstate(pomdp::FireWorld)
    total_size = pomdp.grid_size * grid_size
    s = FireState[]
    probs = Array{Float64,1}(undef,0)

    init_state = pomdp.state
    burning = init_state.burning
    burn_probs = init_state.burn_probs
    fuels = init_state.fuels

    burn_probs_for_obs = deepcopy(burn_probs)
    not_burning = findall(x->x==0, burning)
    all_cells = [1:total_size]
    cells_burning = all_cells[1][minus(not_burning, all_cells[1])]
    for b_i in cells_burning
        burn_probs_for_obs[b_i] = 1.0
    end

    thresholds = collect(1:19)/20
    individual_prob = 1/length(thresholds)
    burns = []
    for threshold_k in thresholds
        burning_k = burn_probs_for_obs .> threshold_k
        # need to check if already in
        if burning_k in burns
            b_idx = findall(x->x==burning_k, burns)
            prob = probs[b_idx[1]]
            probs[b_idx[1]] = prob + individual_prob
        else
            push!(burns, burning_k)
            push!(probs, individual_prob)
            push!(s, FireState(burning_k, burn_probs, fuels))
        end
    end
    return SparseCat(s, normalize!(probs,1))
end


text:
using DelimitedFiles
using FFTW

function create_gaussian(xmax, sigma, res)
    x = [(-xmax + 2*xmax*i/res) for i = 1:res]
    g = (1/(sqrt(2*pi)*sigma))*exp.(-(x/sigma).^2/2)
end

function normalize(a,dx)
    factor = sum(a)
    return a/factor/dx
end

function create_gaussian_file(filename)
    res = 1024
    file = open(filename, "w")
    for i = 1:10
        sigma = i/10
        g = create_gaussian(10, sigma, res)
        println(sum(g))
        for j = 1:res
            write(file, string(g[j])*'\n')
        end
        write(file, "\n\n")
    end

    close(file)
end

function create_fft_gaussian_file(filename)
    res = 1024
    file = open(filename, "w")
    for i = 1:10
        sigma = i/10
        g = create_gaussian(10, sigma, res)
        g = normalize(abs.(fftshift(fft(g))), 20/res)
        println(sum(g))
        for j = 1:res
            write(file, string(g[j])*'\n')
        end
        write(file, "\n\n")
    end

    close(file)
end

max_stars_repo_name: leios/thesis

max_issues_repo_name: leios/thesis

max_forks_repo_name: leios/thesis


text:
using ModelingToolkit
using SteadyStateDiffEq
using Test

@parameters t r
@variables x(t)
D = Differential(t)
eqs = [D(x) ~ x^2 - r]
@named de = ODESystem(eqs)

for factor in [1e-1, 1e0, 1e10],
    u0_p in [(2.34, 2.676), (22.34, 1.632), (0.3, 15.676), (0.3, 0.006)]

    u0 = [x => factor * u0_p[1]]
    p = [r => factor * u0_p[2]]
    ss_prob = SteadyStateProblem(de, u0, p)
    sol = solve(ss_prob, SSRootfind()).u[1]
    @test abs(sol^2 - factor * u0_p[2]) < 1e-8
    ss_prob = SteadyStateProblemExpr(de, u0, p)
    sol_expr = solve(eval(ss_prob), SSRootfind()).u[1]
    @test all(x -> x == 0, sol - sol_expr)
end


text:
include("euler/euler.jl")
using .Primes: prime_sieve
using BenchmarkTools
BenchmarkTools.DEFAULT_PARAMETERS.samples = 100

function compute(n::Int)::Int
    sieve = prime_sieve(n)
    prime_numbers = findall(sieve)
    max_sequence, max_sequence_sum = 0, 0
    for prime ∈ prime_numbers
        max_sequence_sum += prime
        if max_sequence_sum < n
            max_sequence += 1
        else
            break
        end
    end
    for i ∈ max_sequence:-1:0
        for j ∈ 1:length(prime_numbers) - i
            sum_sequence = sum(prime_numbers[j:i + j])
            if sum_sequence > n
                break
            elseif sieve[sum_sequence]
                return sum_sequence
            end
        end
    end
end

compute(100)

compute(1_000)

compute(1_000_000)

@benchmark compute(1_000_000)

max_stars_repo_name: Dynortice/Project-Euler

max_issues_repo_name: Dynortice/Project-Euler

max_forks_repo_name: Dynortice/Project-Euler


text:
using ..MLToolkit.PlotsX
using ..MLToolkit.PlotsX: plot, plot!

function vis(dataset::AbstractDataset, args...; kwargs...)
    p = plot()
    vis!(p, dataset, args...; kwargs...)
    return p
end

vis!(p, d::AbstractDataset, x) = vis!(p, d, (x=x,))

function vis!(p, ::Union{AbstractDataset{2}, AbstractDataset{3}}, nt::NamedTuple)
    plot!(p, LabelledScatter(nt))
end

function vis!(p, d::ImageDataset, nt::NamedTuple{T1, <:NTuple{N, T2}}) where {T1, N, T2<:AbstractArray}
    plot!(p, ImageGrid(invlink(d, cat(values(nt)...; dims=ndims(T2)))))
end


text:
import CLBLAS
import OpenCL

using PyCall

const kernel_source = "
__kernel void mmul(
        const int Mdim,
        const int Ndim,
        const int Pdim,
        __global float* A,
        __global float* B,
        __global float* C)
{
        int k;
        int i = get_global_id(0);
        int j = get_global_id(1);
        float tmp;
        if ((i < Ndim) && (j < Mdim))
        {
                tmp = 0.0f;
                for (k = 0; k < Pdim; k++)
                        tmp += A[i*Ndim+k] * B[k*Pdim+j];
                C[i*Ndim+j] = tmp;
        }
}
"

const kernel_source1 = "
#define BLOCK_SIZE 16
#define AS(i, j) As[j + i * BLOCK_SIZE]
#define BS(i, j) Bs[j + i * BLOCK_SIZE]

///////////////////////////////////////////////////////////////////////////////
//! Matrix multiplication on the device: C = A * B
//! uiWA is A's width and uiWB is B's width
////////////////////////////////////////////////////////////////////////////////
__kernel void
  ommul(int uiWA, int uiWB, int uiWC,
             __global float* C, __global float* A, __global float* B,
             __local float* As, __local float* Bs)
{
  // Block index
  int bx = get_group_id(0);
  int by = get_group_id(1);

  // Thread index
  int tx = get_local_id(0);
  int ty = get_local_id(1);

  // Index of the first sub-matrix of A processed by the block
  int aBegin = uiWA * BLOCK_SIZE * by;

  // Index of the last sub-matrix of A processed by the block
  int aEnd   = aBegin + uiWA - 1;

  // Step size used to iterate through the sub-matrices of A
  int aStep  = BLOCK_SIZE;

  // Index of the first sub-matrix of B processed by the block
  int bBegin = BLOCK_SIZE * bx;

  // Step size used to iterate through the sub-matrices of B
  int bStep  = BLOCK_SIZE * uiWB;

  // Csub is used to store the element of the block sub-matrix
  // that is computed by the thread
  float Csub = 0.0f;

  // Loop over all the sub-matrices of A and B
  // required to compute the block sub-matrix
  for (int a = aBegin, b = bBegin;
       a <= aEnd;
       a += aStep, b += bStep) {

    // Load the matrices from device memory
    // to shared memory; each thread loads
    // one element of each matrix
    AS(ty, tx) = A[a + uiWA * ty + tx];
    BS(ty, tx) = B[b + uiWB * ty + tx];

    // Synchronize to make sure the matrices are loaded
    barrier(CLK_LOCAL_MEM_FENCE);

    // Multiply the two matrices together;
    // each thread computes one element
    // of the block sub-matrix
        #pragma unroll
    for (int k = 0; k < BLOCK_SIZE; ++k)
      Csub += AS(ty, k) * BS(k, tx);

    // Synchronize to make sure that the preceding
    // computation is done before loading two new
    // sub-matrices of A and B in the next iteration
    barrier(CLK_LOCAL_MEM_FENCE);
  }

  // Write the block sub-matrix to device memory;
  // each thread writes one element
  C[get_global_id(1) * get_global_size(0) + get_global_id(0)] = Csub;
}
"

function generateAlmostSqRandomMatrixSize(num::Int)
   # Format is (m,k,n) so matrix mul is (m,n)
   matSizes = Array(Tuple, num)
   for i in 1:num
      matSizes[i] = (rand(1:100) * 16, rand(1:100) * 16, rand(1:100) * 16)
   end
   return matSizes
end

function runTimes(num::Int, device=nothing, context=nothing, queue=nothing, mmul=nothing, ommul=nothing  )
        if(device == nothing)
            device, context, queue = clblas.get_next_compute_context()
        end

        alpha = Float32(5)
        beta  = Float32(2)

        matSizes = generateAlmostSqRandomMatrixSize(num)

        cpuTimes = Array(Int, num)
        data = nothing
        for i in 1:num

           A = rand(Float32, matSizes[i][1], matSizes[i][2])
           B = rand(Float32, matSizes[i][2], matSizes[i][3])
           C = rand(Float32, matSizes[i][1], matSizes[i][3])

           startT = time_ns()
           data = (alpha*A*B) + (beta*C)
           endT = time_ns()
           cpuTimes[i] = endT - startT
           gc()
        end

        gpuMmulTimes2 = zeros(Int, num)
        gpuTimes = Array(Int, num)
        for i in 1:num

           A = clblas.randBuf(matSizes[i][1], matSizes[i][2]; ctx=context, queue=queue)
           cl.api.clWaitForEvents(cl.cl_uint(1), pointer(A.event))
           B = clblas.randBuf(matSizes[i][2], matSizes[i][3]; ctx=context, queue=queue)
           cl.api.clWaitForEvents(cl.cl_uint(1), pointer(B.event))
           C = clblas.randBuf(matSizes[i][1], matSizes[i][3]; ctx=context, queue=queue)
           cl.api.clWaitForEvents(cl.cl_uint(1), pointer(C.event))

           startT = time_ns()
           future = clblas.clblasSgemm(uint32(0), uint32(0), alpha, A, B, beta, C)
           cl.api.clWaitForEvents(cl.cl_uint(1), pointer(future.event))
           endT = time_ns()
           gpuTimes[i] = endT - startT
           gc()

           if(ommul != nothing)
              m = matSizes[i][1]
              k = matSizes[i][2]
              n = matSizes[i][3]

              blocksize = 16
              localmem1 = cl.LocalMem(Float32, blocksize^2)
              localmem2 = cl.LocalMem(Float32, blocksize^2)

              startT = time_ns()
              evt = ommul[queue, (m,), (16,)](n, m, k, A.mem, B.mem, C.mem, localmem1, localmem2)
              cl.api.clWaitForEvents(cl.cl_uint(1), pointer([pointer(evt)]))
              endT = time_ns()
              gpuMmulTimes2[i] = endT - startT
              gc()
           end
        end

         gpuMmulTimes = zeros(Int, num)
#        if(mmul != nothing)
#            for i in 1:num
#                startT = time_ns()
#                m = matSizes[i][1]
#                k = matSizes[i][2]
#                n = matSizes[i][3]
#                A = clblas.randBuf(m, k; ctx=context, queue=queue)
#                cl.api.clWaitForEvents(cl.cl_uint(1), pointer(A.event))
#                B = clblas.randBuf(k, n; ctx=context, queue=queue)
#                cl.api.clWaitForEvents(cl.cl_uint(1), pointer(B.event))
#                C = clblas.randBuf(m, n; ctx=context, queue=queue)
#                cl.api.clWaitForEvents(cl.cl_uint(1), pointer(C.event))

#                global_range = (m, n)
#                evt = mmul[queue, global_range](n, m, k, A.mem, B.mem, C.mem)
#                cl.api.clWaitForEvents(cl.cl_uint(1), pointer([pointer(evt)]))
#                endT = time_ns()
#                gpuMmulTimes[i] = endT - startT
#                gc()
#             end
#        end
     return (cpuTimes, gpuTimes, gpuMmulTimes, gpuMmulTimes2)
end

const clblas = CLBLAS
clblas.setup(true)
using OpenCL: cl

for platform in cl.platforms()
    if platform[:name] == "Portable Computing Language"
        warn("Portable Computing Language platform not yet supported")
        continue
    end

    for device in cl.devices(platform)
        @printf("====================================================\n")
        @printf("Platform name:    %s\n",  platform[:name])
        @printf("Platform profile: %s\n",  platform[:profile])
        @printf("Platform vendor:  %s\n",  platform[:vendor])
        @printf("Platform version: %s\n",  platform[:version])
        @printf("----------------------------------------------------\n")
        @printf("Device name: %s\n", device[:name])
        @printf("Device type: %s\n", device[:device_type])
        @printf("Device mem: %i MB\n",           device[:global_mem_size] / 1024^2)
        @printf("Device max mem alloc: %i MB\n", device[:max_mem_alloc_size] / 1024^2)
        @printf("Device max clock freq: %i MHZ\n",  device[:max_clock_frequency])
        @printf("Device max compute units: %i\n",   device[:max_compute_units])
        @printf("Device max work group size: %i\n", device[:max_work_group_size])
        @printf("Device max work item size: %s\n",  device[:max_work_item_size])

   end
end

device, context, queue = clblas.get_next_compute_context()
#Prepare Kernel to Run Matrix Mul
info("Building The Kernel")
prg  = cl.Program(context, source=kernel_source) |> cl.build!
mmul = cl.Kernel(prg, "mmul")
info("Kernel is ready")

prg1  = cl.Program(context, source=kernel_source1) |> cl.build!
ommul = cl.Kernel(prg1, "ommul")
info("Kernel-2 is ready")

runTimes(5, device, context, queue, mmul, ommul)

#print("Debug is ready!")
#readline()

num = int(ARGS[1])
cpuTimes, gpuTimes, gpuMmulTimes, gpuMmulTimes2 = runTimes(num, device, context, queue, mmul, ommul)

println("Average CPU    :", sum(cpuTimes)/num)
println("Average GPU    :", sum(gpuTimes)/num)
println("Average GPU-Mul:", sum(gpuMmulTimes)/num)
println("Average GPU-Mul2:", sum(gpuMmulTimes2)/num)
clblas.teardown()

sleep(1)

@pyimport matplotlib.pyplot as plt
plt.plot([1:num], gpuMmulTimes2, color="green", linewidth=2.0, linestyle="--", label="GPU-Mul2")
plt.plot([1:num], cpuTimes, color="red", linewidth=2.0, linestyle="--", label="CPU")
plt.plot([1:num], gpuTimes, color="blue", linewidth=2.0, linestyle="--", label="GPU")
#plt.plot([1:num], gpuMmulTimes, color="yellow", linewidth=2.0, linestyle="--", label="GPU-Mul")

plt.ylabel("time ns")
plt.title("CPU vs GPU times")
plt.show()

function gemm(m, k, n, alpha, beta,  times)
      total = 0
      for i in 1:times
         A = rand(Float32, m, k)
         B = rand(Float32, k, n)
         C = rand(Float32, m, n)
         tic()
         C = alpha*A*B + beta*C
         total += toq()
      end
      (total / times) * 10 ^ 9
end


text:
# find expression of projections on cones and their derivatives here:
#   https://stanford.edu/~boyd/papers/pdf/cone_prog_refine.pdf

"""
    projection_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Zeros) where {T}

projection of vector `v` on zero cone i.e. K = {0}
"""
function projection_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Zeros) where {T}
    return FillArrays.Zeros{T}(size(v))
end

"""
    projection_on_set(::AbstractDistance, ::MOI.Reals, v::Array{T}) where {T}

projection of vector `v` on real cone i.e. K = R
"""
function projection_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Reals) where {T}
    return v
end

function projection_on_set(::DefaultDistance, v::T, set::MOI.EqualTo) where {T}
    return zero(T) + set.value
end

function projection_on_set(::DefaultDistance, v::T, set::MOI.LessThan) where {T}
    return min(v, MOI.constant(set))
end

function projection_on_set(::DefaultDistance, v::T, set::MOI.GreaterThan) where {T}
    return max(v, MOI.constant(set))
end

"""
    projection_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Nonnegatives) where {T}

projection of vector `v` on Nonnegative cone i.e. K = R^n+
"""
function projection_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Nonnegatives) where {T}
    return max.(v, zero(T))
end

"""
    projection_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Nonpositives) where {T}

projection of vector `v` on Nonpositive cone i.e. K = R^n-
"""
function projection_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Nonpositives) where {T}
    return min.(v, zero(T))
end

"""
    projection_on_set(::NormedEpigraphDistance{p}, v::AbstractVector{T}, ::MOI.SecondOrderCone) where {T}

projection of vector `v` on second order cone i.e. K = {(t, x) ∈ R+ × Rn |  ||x|| ≤ t }
"""
function projection_on_set(::NormedEpigraphDistance{p}, v::AbstractVector{T}, ::MOI.SecondOrderCone) where {p, T}
    t = v[1]
    x = v[2:length(v)]
    norm_x = LinearAlgebra.norm(x, p)
    if norm_x <= t
        return copy(v)
    elseif norm_x <= -t
        return zeros(T, size(v))
    end
    result = zeros(T, size(v))
    result[1] = one(T)
    result[2:length(v)] = x / norm_x
    result *= (norm_x + t) / 2
    return result
end

function projection_on_set(::DefaultDistance, v::AbstractVector{T}, cone::MOI.SecondOrderCone) where {T}
    return projection_on_set(NormedEpigraphDistance{2}(), v, cone)
end

"""
    projection_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.PositiveSemidefiniteConeTriangle) where {T}

projection of vector `v` on positive semidefinite cone i.e. K = S^n⨥
"""
function projection_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.PositiveSemidefiniteConeTriangle) where {T}
    dim = isqrt(2*length(v))
    X = unvec_symm(v, dim)
    λ, U = LinearAlgebra.eigen(X)
    D = LinearAlgebra.Diagonal(max.(λ, 0))
    return vec_symm(U * D * U')
end

"""
    unvec_symm(x, dim)

Returns a dim-by-dim symmetric matrix corresponding to `x`.

`x` is a vector of length dim*(dim + 1)/2, corresponding to a symmetric matrix
```
X = [ X11  X12 ... X1k
      X21  X22 ... X2k
      ...
      Xk1  Xk2 ... Xkk ],
```
where `vec(X) = (X11, X12, X22, X13, X23, X33, ..., Xkk)`.

### Note on inner products

Note that the scalar product for the symmetric matrix in its vectorized form is
the sum of the pairwise product of the diagonal entries plus twice the sum of
the pairwise product of the upper diagonal entries; see [p. 634, 1].
Therefore, this transformation breaks inner products:
```
dot(unvec_symm(x, dim), unvec_symm(y, dim)) != dot(x, y).
```

### References

[1] Boyd, S. and Vandenberghe, L.. *Convex optimization*. Cambridge university press, 2004.
"""
function unvec_symm(x, dim=isqrt(2length(x)))
    X = zeros(eltype(x), dim, dim)
    idx = 1
    for i in 1:dim
        for j in 1:i
            X[j,i] = X[i,j] = x[idx]
            idx += 1
        end
    end
    return X
end

"""
    vec_symm(X)

Returns a vectorized representation of a symmetric matrix `X`.
`vec(X) = (X11, X12, X22, X13, X23, X33, ..., Xkk)`

### Note on inner products

Note that the scalar product for the symmetric matrix in its vectorized form is
the sum of the pairwise product of the diagonal entries plus twice the sum of
the pairwise product of the upper diagonal entries; see [p. 634, 1].
Therefore, this transformation breaks inner products:
```
dot(vec_symm(X), vec_symm(Y)) != dot(X, Y).
```

### References

[1] Boyd, S. and Vandenberghe, L.. *Convex optimization*. Cambridge university press, 2004.

"""
function vec_symm(X)
    return X[LinearAlgebra.triu(trues(size(X)))]
end

"""
    projection_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.ExponentialCone) where {T}

projection of vector `v` on closure of the exponential cone
i.e. `cl(Kexp) = {(x,y,z) | y e^(x/y) <= z, y>0 } U {(x,y,z)| x <= 0, y = 0, z >= 0}`.

References:
* [Proximal Algorithms, 6.3.4](https://web.stanford.edu/~boyd/papers/pdf/prox_algs.pdf)
by Neal Parikh and Stephen Boyd.
* [Projection, presolve in MOSEK: exponential, and power cones]
(https://docs.mosek.com/slides/2018/ismp2018/ismp-friberg.pdf) by Henrik Friberg
* [Projection onto the exponential cone: a univariate root-finding problem]
(https://docs.mosek.com/whitepapers/expcone-proj.pdf) by Henrik Friberg
"""
function projection_on_set(::DefaultDistance, v::AbstractVector{T}, s::MOI.ExponentialCone; tol=1e-8) where {T}
    _check_dimension(v, s)

    if _in_exp_cone(v; dual=false)
        return SVector{3}(v)
    end
    if _in_exp_cone(-v; dual=true)
        # if in polar cone Ko = -K*
        return zeros(SVector{3,T})
    end
    if v[1] <= 0 && v[2] <= 0
        return @SVector([v[1], 0, max(v[3],0)])
    end

    return _exp_cone_proj_case_4(v; tol=tol)
end

function _in_exp_cone(v::AbstractVector{T}; dual=false, tol=1e-8) where {T}
    if dual
        return (
            (isapprox(v[1], 0, atol=tol) && v[2] >= 0 && v[3] >= 0) ||
            (v[1] < 0 && v[1]*exp(v[2]/v[1]) + ℯ * v[3] >= tol)
        )
    else
        return (
            (v[1] <= 0 && isapprox(v[2], 0, atol=tol) && v[3] >= 0) ||
            (v[2] > 0 && v[2] * exp(v[1] / v[2]) - v[3] <= tol)
        )
    end
end

function _exp_cone_proj_case_4(v::AbstractVector{T}; tol=1e-8) where {T}
    # Try Heuristic solutions [Friberg 2021, Lemma 5.1]
    # vp = proj onto primal cone, vd = proj onto polar cone
    vp = SVector{3,T}(min(v[1], 0), zero(T), max(v[3], 0))
    vd = SVector{3,T}(zero(T), min(v[2], 0), min(v[3], 0))
    if v[2] > 0
        zp = max(v[3], v[2]*exp(v[1]/v[2]))
        if zp - v[3] < norm(vp - v)
            vp = SVector{3,T}(v[1], v[2], zp)
        end
    end
    if v[1] > 0
        zd = min(v[3], -v[1]*exp(v[2]/v[1] - 1))
        if v[3] - zd < norm(vd - v)
            vd = SVector{3,T}(v[1], v[2], zd)
        end
    end

    # Check if heuristics above approximately satisfy the optimality conditions
    opt_norm = norm(vp + vd - v)
    opt_ortho = abs(dot(vp, vd))
    if norm(v - vp) < tol || norm(v - vd) < tol || (opt_norm < tol && opt_ortho < tol)
        return vp
    end

    # Failure of heuristics -> non heuristic solution
    # Ref: https://docs.mosek.com/slides/2018/ismp2018/ismp-friberg.pdf, p47-48
    # Thm: h(x) is smooth, strictly increasing, and changes sign on domain
    r, s, t = v[1], v[2], v[3]
    h(x) = (((x-1)*r + s) * exp(x) - (r - x*s)*exp(-x))/(x^2 - x + 1) - t

    # Note: won't both be Inf by case 3 of projection
    lb = r > 0 ? 1 - s/r : -Inf
    ub = s > 0 ? r/s : Inf

    # Deal with ±Inf bounds
    if isinf(lb)
        lb = min(ub-0.125, -0.125)
        for _ in 1:10
            h(lb) < 0 && break
            ub = lb
            lb *= 2
        end
    end
    if isinf(ub)
        ub = max(lb+0.125, 0.125)
        for _ in 1:10
            h(ub) > 0 && break
            lb = ub
            ub *= 2
        end
    end

    # Check bounds
    if !(h(lb) < 0 && h(ub) > 0)
        error("Failure to find bracketing interval for exp cone projection.")
    end

    x = _bisection(h, lb, ub)
    if x === nothing
        error("Failure in root-finding for exp cone projection with boundaries ($lb, $ub).")
    end

    return ((x - 1) * r + s)/(x^2 - x + 1) * SVector{3,T}(x, 1, exp(x))
end

"""
    projection_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.DualExponentialCone) where {T}

projection of vector `v` on the dual exponential cone
i.e. `Kexp^* = {(u,v,w) | u < 0, -u*exp(v/u) <= ew } U {(u,v,w)| u == 0, v >= 0, w >= 0}`.

References:
* [Proximal Algorithms, 6.3.4](https://web.stanford.edu/~boyd/papers/pdf/prox_algs.pdf)
by Neal Parikh and Stephen Boyd.
* [Projection, presolve in MOSEK: exponential, and power cones](https://docs.mosek.com/slides/2018/ismp2018/ismp-friberg.pdf)
by Henrik Friberg
"""
function projection_on_set(d::DefaultDistance, v::AbstractVector{T}, ::MOI.DualExponentialCone) where {T}
    p = projection_on_set(d, -v, MOI.ExponentialCone())
    return SVector{3,T}(v[1] + p[1], v[2] + p[2], v[3] + p[3])
end

"""
    projection_on_set(::DefaultDistance, v::AbstractVector{T}, sets::Array{<:MOI.AbstractSet})

Projection onto `sets`, a product of sets
"""
function projection_on_set(::DefaultDistance, v::AbstractVector{T}, sets::Array{<:MOI.AbstractSet}) where {T}
    length(v) == length(sets) || throw(DimensionMismatch("Mismatch between value and set"))
    return reduce(vcat, (projection_on_set(DefaultDistance(), v[i], sets[i]) for i in eachindex(sets)))
end

"""
    projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Zeros) where {T}

derivative of projection of vector `v` on zero cone i.e. K = {0}^n
"""
function projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Zeros) where {T}
    return FillArrays.Zeros(length(v), length(v))
end

"""
    projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Reals) where {T}

derivative of projection of vector `v` on real cone i.e. K = R^n
"""
function projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Reals) where {T}
    return FillArrays.Eye(length(v))
end

"""
    projection_gradient_on_set(::DefaultDistance, v::T, ::MOI.EqualTo)
"""
function projection_gradient_on_set(::DefaultDistance, ::T, ::MOI.EqualTo) where {T}
    return zero(T)
end

function projection_gradient_on_set(::DefaultDistance, v::T, s::MOI.LessThan) where {T}
    return oneunit(T) * (v <= MOI.constant(s))
end

function projection_gradient_on_set(::DefaultDistance, v::T, s::MOI.GreaterThan) where {T}
    return oneunit(T) * (v >= MOI.constant(s))
end

"""
    projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Nonnegatives) where {T}

derivative of projection of vector `v` on Nonnegative cone i.e. K = R^n+
"""
function projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Nonnegatives) where {T}
    y = (sign.(v) .+ one(T))/2
    return LinearAlgebra.Diagonal(y)
end

"""
    projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Nonpositives) where {T}

derivative of projection of vector `v` on Nonpositives cone i.e. K = R^n-
"""
function projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.Nonpositives) where {T}
    y = @. (-sign(v) + one(T))/2
    return LinearAlgebra.Diagonal(y)
end

"""
    projection_gradient_on_set(::NormedEpigraphDistance{p}, v::AbstractVector{T}, ::MOI.SecondOrderCone) where {T}

derivative of projection of vector `v` on second order cone i.e. K = {(t, x) ∈ R+ × Rn |  ||x|| ≤ t }
"""
function projection_gradient_on_set(::NormedEpigraphDistance{p}, v::AbstractVector{T}, ::MOI.SecondOrderCone) where {p,T}
    n = length(v)
    t = v[1]
    x = v[2:n]
    norm_x = LinearAlgebra.norm(x, p)
    if norm_x <= t
        return Matrix{T}(LinearAlgebra.I,n,n)
    elseif norm_x <= -t
        return zeros(T, n, n)
    end
    result = [
        norm_x     x';
        x          (norm_x + t)*Matrix{T}(LinearAlgebra.I,n-1,n-1) - (t/(norm_x^2))*(x*x')
    ]
    result ./= (2 * norm_x)
    return result
end

function projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, cone::MOI.SecondOrderCone) where {T}
    return projection_gradient_on_set(NormedEpigraphDistance{2}(), v, cone)
end

"""
    projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, cone::MOI.PositiveSemidefiniteConeTriangle) where {T}

derivative of projection of vector `v` on positive semidefinite cone i.e. K = S^n⨥
"""
function projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.PositiveSemidefiniteConeTriangle) where {T}
    n = length(v)
    dim = isqrt(2n)
    X = unvec_symm(v, dim)
    λ, U = LinearAlgebra.eigen(X)
    Tp = promote_type(T, Float64)

    # if all the eigenvalues are >= 0
    if all(λi ≥ zero(λi) for λi in λ)
        return Matrix{Tp}(LinearAlgebra.I, n, n)
    end

    # k is the number of negative eigenvalues in X minus ONE
    k = count(λi < 1e-4 for λi in λ)

    y = zeros(Tp, n)
    D = zeros(Tp, n, n)

    for idx in 1:n
        # set eigenvector
        y[idx] = 1

        # defining matrix B
        X̃ = unvec_symm(y, dim)
        B = U' * X̃ * U

        for i in 1:size(B)[1] # do the hadamard product
            for j in 1:size(B)[2]
                if (i <= k && j <= k)
                    @inbounds B[i, j] = 0
                elseif (i > k && j <= k)
                    λpi = max(λ[i], zero(Tp))
                    λmj = -min(λ[j], zero(Tp))
                    @inbounds B[i, j] *= λpi / (λmj + λpi)
                elseif (i <= k && j > k)
                    λmi = -min(λ[i], zero(Tp))
                    λpj = max(λ[j], zero(Tp))
                    @inbounds B[i, j] *= λpj / (λmi + λpj)
                end
            end
        end
        @inbounds D[idx, :] = vec_symm(U * B * U')
        # reset eigenvector
        @inbounds y[idx] = 0
    end
    return D
end

"""
    projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.ExponentialCone) where {T}

derivative of projection of vector `v` on closure of the exponential cone,
i.e. `cl(Kexp) = {(x,y,z) | y e^(x/y) <= z, y>0 } U {(x,y,z)| x <= 0, y = 0, z >= 0}`.

References:
* [Solution Refinement at Regular Points of Conic Problems](https://stanford.edu/~boyd/papers/cone_prog_refine.html)
by Enzo Busseti, Walaa M. Moursi, and Stephen Boyd
"""
function projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, s::MOI.ExponentialCone) where {T}
    _check_dimension(v, s)

    if _in_exp_cone(v; dual=false)
        return SMatrix{3,3,T}(I)
    end
    if _in_exp_cone(-v; dual=true)
        # if in polar cone Ko = -K*
        return zeros(SMatrix{3,3,T})
    end
    if v[1] <= 0 && v[2] <= 0
        return @SMatrix(T[
            1 0 0
            0 0 0
            0 0 (v[3] >= 0)
        ])
    end

    z1, z2, z3 = _exp_cone_proj_case_4(v)
    nu = z3 - v[3]
    rs = z1/z2
    exp_rs = exp(rs)

    mat = inv(@SMatrix([
        1+nu*exp_rs/z2     -nu*exp_rs*rs/z2       0     exp_rs;
        -nu*exp_rs*rs/z2   1+nu*exp_rs*rs^2/z2    0     (1-rs)*exp_rs;
        0                  0                      1     -1
        exp_rs             (1-rs)*exp_rs          -1    0
    ]))
    return SMatrix{3,3}(@view(mat[1:3,1:3]))
end

"""
    projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.DualExponentialCone) where {T}

derivative of projection of vector `v` on the dual exponential cone,
i.e. `Kexp^* = {(u,v,w) | u < 0, -u*exp(v/u) <= ew } U {(u,v,w)| u == 0, v >= 0, w >= 0}`.

References:
* [Solution Refinement at Regular Points of Conic Problems]
(https://stanford.edu/~boyd/papers/cone_prog_refine.html)
by Enzo Busseti, Walaa M. Moursi, and Stephen Boyd
"""
function projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, ::MOI.DualExponentialCone) where {T}
    # from Moreau decomposition: x = P_K(x) + P_-K*(x)
    return I - projection_gradient_on_set(DefaultDistance(), -v, MOI.ExponentialCone())
end

"""
    projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, sets::AbstractVector{<:MOI.AbstractSet})

Derivative of the projection of vector `v` on product of `sets`
projection_gradient_on_set[i,j] = ∂projection_on_set[i] / ∂v[j] where `projection_on_set` denotes projection of `v` on `cone`

Find expression of projections on cones and their derivatives here: https://stanford.edu/~boyd/papers/pdf/cone_prog_refine.pdf
"""
function projection_gradient_on_set(::DefaultDistance, v::AbstractVector{T}, sets::AbstractVector{<:MOI.AbstractSet}) where {T}
    length(v) == length(sets) || throw(DimensionMismatch("Mismatch between value and set"))
    return BlockDiagonal([projection_gradient_on_set(DefaultDistance(), v[i], sets[i]) for i in eachindex(sets)])
end

"""
    projection_on_set(::DefaultDistance, V::AbstractVector{T}, s::NormBallNuclear{T}) where {T}

projection of matrix `V` onto nuclear norm ball
"""
function projection_on_set(d::DefaultDistance, V::AbstractMatrix{T}, s::NormNuclearBall{T}) where {T}
    U, sing_val, Vt = LinearAlgebra.svd(V)
    if (sum(sing_val) <= s.radius)
        return V
    end
    sing_val_proj = projection_on_set(d, sing_val, ProbabilitySimplex(length(sing_val), s.radius))
    return U * Diagonal(sing_val_proj) * Vt'
end

# initial implementation in FrankWolfe.jl
function projection_on_set(::DefaultDistance, v::AbstractVector{T}, s::ProbabilitySimplex{T}) where {T}
    _check_dimension(v, s)
    # TODO: allocating a ton, should implement the recent non-sorting alg
    n = length(v)
    if sum(v) ≈ s.radius && all(>=(0), v)
        return v
    end
    rev = v .- maximum(v)
    u = sort(rev, rev=true)
    cssv = cumsum(u)
    rho = sum(eachindex(u)) do idx
        u[idx] * idx > (cssv[idx] - s.radius)
    end - 1
    theta = (cssv[rho+1] - s.radius) / (rho + 1)
    w = clamp.(rev .- theta, 0.0, Inf)
    return w
end

function projection_on_set(::DefaultDistance, v::AbstractVector{T}, s::StandardSimplex{T}) where {T}
    _check_dimension(v, s)
    n = length(v)
    if sum(v) ≤ s.radius && all(>=(0), v)
        return v
    end
    x = copy(v)
    sum_pos = zero(T)
    for idx in eachindex(x)
        if x[idx] < 0
            x[idx] = 0
        else
            sum_pos += x[idx]
        end
    end
    # at least one positive element
    if sum_pos > 0
        @. x = x / sum_pos * s.radius
    end
    return x
end

function projection_on_set(::DefaultDistance, v::AbstractVector{T}, s::NormInfinityBall{T}) where {T}
    if norm(v, Inf) <= s.radius
        return v
    end
    return clamp.(v, -s.radius, s.radius)
end

function projection_on_set(::DefaultDistance, v::AbstractVector{T}, s::NormTwoBall{T}) where {T}
    nv = norm(v)
    if nv <= s.radius
        return v
    end
    return v .* s.radius ./ nv
end

# inspired by https://github.com/MPF-Optimization-Laboratory/ProjSplx.jl
function projection_on_set(::DefaultDistance, v::AbstractVector{T}, s::NormOneBall{T}) where {T}
    n = length(v)
    if norm(v, 1) ≤ τ
        return v
    end
    u = abs.(v)
    # simplex projection
    bget = false
    s_indices = sortperm(u, rev=true)
    tsum = zero(τ)

    @inbounds for i in 1:n-1
        tsum += u[s_indices[i]]
        tmax = (tsum - τ) / i
        if tmax ≥ u[s_indices[i+1]]
            bget = true
            break
        end
    end
    if !bget
        tmax = (tsum + u[s_indices[n]] - τ) / n
    end

    @inbounds for i in 1:n
        u[i] = max(u[i] - tmax, 0)
        u[i] *= sign(v[i])
    end
    return u
end


text:
abstract type AbstractGraphProblem <: AbstractProblem end

import Base: length

using LightGraphs, SimpleWeightedGraphs

struct MST <: AbstractGraphProblem
    g::Any
    optimum::Real
    function MST(g; optimum::Real = -mst_value(g))
        new(g, optimum)
    end
end

function fitness(x::BitArray, problem::MST)
    penalty = 100000000
    g = problem.g

    subg = graph_bitstring(g, x)

    cc = connected_components(subg)
    if length(cc) != 1
        return -1 * (penalty + length(cc))
    end
    weights = sum(subg.weights) / 2 #Becuase subg.weights counts each edge twice.

    return -weights
end

function optimum(problem::MST)
    return problem.optimum
end

length(problem::MST) = nv(problem.g)

function TG(n)
    p = floor(Int, n / 4)
    q = floor(Int, n / 2)
    a = n^2
    g = SimpleWeightedGraph(complete_graph(q), 1)
    add_vertices!(g, 2 * p)
    for j = q+1:2:q+2p
        add_edge!(g, j, j - 1, 2 * a)
        add_edge!(g, j, j + 1, 2 * a)
        add_edge!(g, j + 1, j - 1, 3 * a)
    end
    g
end

#
function ER(n::Integer)
    g = erdos_renyi(n, 2 * Base.Math.log(n) / n)
    egs = collect(edges(g))
    k = SimpleWeightedGraph(n)
    for edge in egs
        add_edge!(k, src(edge), dst(edge), rand(1:n^2))
    end
    if n - 1 != length(prim_mst(k))
        return ER(n)
    end
    k
end

function Kn(n::Integer)
    g = complete_graph(n)
    egs = collect(edges(g))
    k = SimpleWeightedGraph(n)
    for edge in egs
        add_edge!(k, src(edge), dst(edge), rand(1:n^2))
    end
    if n - 1 != length(prim_mst(k))
        return ER(n)
    end
    k
end

#
#
# using GraphPlot
# g = ER(100)
# g.weights
#
#

#
#
struct MaximumMatching <: AbstractGraphProblem
    g::Any
    optimum::Real
    function MaximumMatching(g, optimum::Real)
        new(g, optimum)
    end
end

function fitness(x::BitArray, problem::MaximumMatching)
    h = copy(problem.g)

    for item in findall(row -> row == 0, x)
        edge = collect(edges(problem.g))[item]
        rem_edge!(h, edge)
    end

    degreeh = degree(h)
    dh = degreeh
    penalty = (ne(problem.g) + 1) * sum([max(0, i - 1) for i in dh])
    ne(h) - penalty
end

function optimum(problem::MaximumMatching)
    return problem.optimum
end

length(problem::MaximumMatching) = ne(problem.g)

function GHL(h, l)

    g = SimpleGraph(h * l)
    function nodeindex(L, H, l, h)
        return (h - 1) * L + l
    end

    for i = 1:l
        for j = 1:h
            if i != l
                if i % 2 == 1
                    add_edge!(g, nodeindex(l, h, i, j), nodeindex(l, h, i + 1, j))
                else
                    for k = 1:h
                        add_edge!(g, nodeindex(l, h, i, j), nodeindex(l, h, i + 1, k))
                    end
                end
            end
        end
    end
    g
end


text:
using DiffEqBayes, OrdinaryDiffEq, RecursiveArrayTools, Distributions, Plots, StatsPlots, BenchmarkTools, TransformVariables, CmdStan, DynamicHMC

function pendulum(du,u,p,t)
    ω,L = p
    x,y = u
    du[1] = y
    du[2] = - ω*y -(9.8/L)*sin(x)
end

u0 = [1.0,0.1]
tspan = (0.0,10.0)
prob1 = ODEProblem(pendulum,u0,tspan,[1.0,2.5])

sol = solve(prob1,Tsit5())
plot(sol)

t = collect(range(1,stop=10,length=10))
randomized = VectorOfArray([(sol(t[i]) + .01randn(2)) for i in 1:length(t)])
data = convert(Array,randomized)

scatter!(data')

priors = [Uniform(0.1,3.0), Normal(3.0,1.0)]

bayesian_result = turing_inference(prob1,Tsit5(),t,data,priors;num_samples=10_000,
                                   syms = [:omega,:L])

plot(bayesian_result)

plot(bayesian_result, colordim = :parameter)

@btime bayesian_result = turing_inference(prob1,Tsit5(),t,data,priors;syms = [:omega,:L],num_samples=10_000)

@btime bayesian_result = stan_inference(prob1,t,data,priors;num_samples=10_000,printsummary=false)

@btime bayesian_result = dynamichmc_inference(prob1,Tsit5(),t,data,priors;num_samples = 10_000)


text:
include("../../__lib__/std/datastructs/src/datastructs_module.jl")
include("../../__lib__/std/util/src/util_module.jl")

module geom

using ..datastructs
using ..util
using LinearAlgebra
using Random
using PyPlot
PyPlot.pygui(true)

# =========================================================================== #
# Types
# =========================================================================== #
include("point.jl")
include("line.jl")
include("circle.jl")
include("quad.jl")
include("triangle.jl")
include("polygon.jl")

# =========================================================================== #
# Operations on types
# =========================================================================== #

# =========================================================================== #
# Mixed operations between types
# =========================================================================== #

# =========================================================================== #
# General, miscellenious types, operations
# =========================================================================== #
include("exterma.jl")
include("rotation_matrix.jl")
include("general.jl")

# =========================================================================== #
# Mesh generation
# =========================================================================== #
include("distance.jl")
include("convex_hull.jl")
include("delaunay.jl")
include("mesh_module.jl")

end # module

max_stars_repo_name: HomoModelicus/julia

max_issues_repo_name: HomoModelicus/julia

max_forks_repo_name: HomoModelicus/julia


text:
module TestTry

using ArgCheck: @check
using Reagents
using Reagents: CAS, Computed, Map, Return, WithNack
using Reagents.Internal: ReturnIfBlocked, maysync
using Test
using ..Utils: @test_error, ⊏

function test_try_cas()
    ref = Reagents.Ref(0)
    @test Reagents.try!(CAS(ref, 1, 2)) === nothing
    @test ref[] == 0
    @test Reagents.try!(CAS(ref, 0, 2)) !== nothing
    @test ref[] == 2
end

function test_try_2cas()
    ref1 = Reagents.Ref(0)
    ref2 = Reagents.Ref(0)
    @test Reagents.try!(CAS(ref1, 1, 2) ⨟ CAS(ref2, 0, 3)) === nothing
    @test ref1[] == ref2[] == 0
    @test Reagents.try!(CAS(ref1, 0, 2) ⨟ CAS(ref2, 0, 3)) !== nothing
    @test ref1[] == 2
    @test ref2[] == 3
end

function test_trysync_requires_blocking_reagent()
    ref = Reagents.Ref(0)
    cas = CAS(ref, 1, 2)
    @check !maysync(cas)
    @check !maysync(cas | Map(Some))  # used in `trysync!`
    err = @test_error Reagents.trysync!(cas)
    @test "synchronizing continuation is required" ⊏ sprint(showerror, err)
end

function test_trysync_retries()
    state = Ref(0)
    ref = Reagents.Ref(10)
    reagent = Computed() do _
        old = state[] += 1  # eventually correct
        CAS(ref, old, 111)
    end
    Reagents.trysync!(reagent)
    @test ref[] == 111
end

function test_trysync_nack()
    send_nack, receive_nack = Reagents.channel(Int, Nothing)
    never, _ = Reagents.channel(Nothing)
    reagent = WithNack() do nack
        Reagents.dissolve(Return(111) ⨟ send_nack ⨟ nack)
        @test Reagents.trysync!(receive_nack) === nothing  # not yet NACK'ed
        return never
    end
    @test Reagents.trysync!(receive_nack) === nothing  # not yet NACK'ed
    @test Reagents.trysync!(reagent) === nothing
    @test Reagents.trysync!(receive_nack) == Some(111)  # now NACK'ed
end

# Not used anywhere, but this is the behavior implemented:
function test_rib_pre_cas()
    never, _ = Reagents.channel(Nothing)
    ref = Reagents.Ref(111)
    @test (CAS(ref, 111, 222) ⨟ ReturnIfBlocked(:yes) ⨟ never)() == :yes
    @test ref[] == 222
end

end  # module


text:
# Load Julia packages (libraries) needed.

using Pkg, DrWatson

#@quickactivate "StstisticalRethinkingStan"
using StanSample
using StatisticalRethinking

df = DataFrame(CSV.File(sr_datadir("milk.csv")))
df = filter(row -> !(row[:neocortex_perc] == "NA"), df);
df[!, :neocortex_perc] = parse.(Float64, df[:, :neocortex_perc])
df[!, :lmass] = log.(df[:, :mass])
scale!(df, [:kcal_per_g, :neocortex_perc, :lmass])

# ### snippet 5.35

stan5_5 = "
data {
 int < lower = 1 > N; // Sample size
 vector[N] K; // Outcome
 vector[N] NC; // Predictor
}

parameters {
 real a; // Intercept
 real bN; // Slope (regression coefficients)
 real < lower = 0 > sigma;    // Error SD
}

model {
  vector[N] mu;               // mu is a vector
  a ~ normal(0, 0.2);           //Priors
  bN ~ normal(0, 0.5);
  sigma ~ exponential(1);
  mu = a + bN * NC;
  K ~ normal(mu , sigma);     // Likelihood
}
";

# Define the SampleModel and set the output format to :mcmcchains.

m5_5s = SampleModel("m5.5", stan5_5);

# Input data for cmdstan

m5_5_data = Dict("N" => size(df, 1), "NC" => df[!, :neocortex_perc_s],
    "K" => df[!, :kcal_per_g_s]);

# Sample using StanSample

rc5_5s = stan_sample(m5_5s, data=m5_5_data);

if success(rc5_5s)

  # Describe the draws

  post5_5s_df = read_samples(m5_5s, :dataframe)
  part5_5s = read_samples(m5_5s, :particles)
  quap(m5_5s).particles |> display

end


text:
holidays = readcsv(Pkg.dir("SmartMeterAnalytics/data/holidays.csv"), Int)
holidays = Date[Date(holidays[i,1], holidays[i,2], holidays[i,3]) for i in 1:size(holidays, 1)]

"""Converts timestamp to Ontario-specific time-of-use category, with holidays defined for 2009-2015"""
#TODO: Generalize to other jurisdictions
tou(dt::TimeType) = if isnight(dt) || dayofweek(dt) > 5 || isholiday(dt) # Evening or Weekend or Holiday
    return :OffPeak
elseif 5 <= month(dt) <= 10 # Cooling season
    return ismidday(dt) ? :OnPeak : :MidPeak
else # Heating season
    return ismidday(dt) ? :MidPeak : :OnPeak
end #if

isholiday(dt::TimeType) = length(searchsorted(holidays, Date(DateTime(dt)))) > 0
isnight(dt::TimeType) = !(7 <= hour(dt) < 19)
ismidday(dt::TimeType) = 11 <= hour(dt) < 17

max_stars_repo_name: GordStephen/SmartMeterAnalytics

max_issues_repo_name: GordStephen/SmartMeterAnalytics

max_forks_repo_name: GordStephen/SmartMeterAnalytics