Skip to content

Commit

Permalink
Add Sources
Browse files Browse the repository at this point in the history
  • Loading branch information
eugenebokhan authored Jun 18, 2024
1 parent cb738be commit ae3be0d
Show file tree
Hide file tree
Showing 86 changed files with 2,219 additions and 2 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Test Swift Package

on:
pull_request:
branches: [main]

jobs:
test:
runs-on: macos-latest

steps:
- uses: actions/checkout@v3
- uses: swift-actions/setup-swift@v2
with:
swift-version: '5.9'

- name: Build
run: swift build

- name: Run tests
run: swift test
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,6 @@ fastlane/test_output
# https://github.com/johnno1962/injectionforxcode

iOSInjectionProject/
*.DS_Store
*.swiftpm
Package.resolved
5 changes: 5 additions & 0 deletions .spi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
version: 1
builder:
configs:
- documentation_targets: [SIMDTools]
scheme: SIMDTools
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2024 computer-graphics-tools
Copyright (c) 2024 Eugene Bokhan

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
40 changes: 40 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// swift-tools-version: 5.9

import PackageDescription
import CompilerPluginSupport

let package = Package(
name: "SIMDTools",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6),
.macCatalyst(.v13)
],
products: [
.library(
name: "SIMDTools",
targets: ["SIMDTools"]
),
],
dependencies: [
.package(url: "https://github.com/apple/swift-syntax.git", from: "510.0.2")
],
targets: [
.macro(
name: "SIMDToolsMacros",
dependencies: [
.product(name: "SwiftSyntaxMacros", package: "swift-syntax"),
.product(name: "SwiftCompilerPlugin", package: "swift-syntax")
]
),
.target(name: "SIMDTools", dependencies: ["SIMDToolsMacros"]),
.testTarget(
name: "SIMDToolsTests",
dependencies: [
"SIMDTools",
]
),
]
)
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,35 @@
# simd-tools
# SIMDTools

[![Platform Compatibility](https://img.shields.io/badge/Platforms-iOS%20|%20macOS%20|%20watchOS%20|%20tvOS-brightgreen)](https://swift.org/platforms/)
[![Swift Version](https://img.shields.io/badge/Swift-5.9-orange)](https://swift.org)

<p align="left">
<img src="Sources/SIMDTools/SIMDTools.docc/Resources/documentation-art/simd-tools@2x.png", width="120">
</p>

Welcome to the documentation for the `SIMDTools` Swift package. This package provides utility functions and extensions for working with SIMD matrices and vectors in Swift.

## Overview

The `simd-tools` package includes:

- `Angle` struct for representing angles.
- Extensions for `float3x3` and `float4x4` to perform various matrix transformations.
- Utility functions such as `clamp`, `saturate`, and `interpolate`.

## Install via [SwiftPM](https://swift.org/package-manager/)

```swift
.package(url: "https://github.com/computer-graphics-tools/simd-tools", from: "0.0.1")
```

### Usage

- [Working With Angles](Sources/SIMDTools/SIMDTools.docc/WorkingWithAngles.md)
- [Working With 3x3 Matrices](Sources/SIMDTools/SIMDTools.docc/WorkingWith3x3Matrices.md)
- [Working With 4x4 Matrices](Sources/SIMDTools/SIMDTools.docc/WorkingWith4x4Matrices.md)
- [Helper Functions](Sources/SIMDTools/SIMDTools.docc/HelperFunctions.md)

## License

MetalTools is licensed under [MIT license](LICENSE).
244 changes: 244 additions & 0 deletions Sources/SIMDTools/Angle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
import simd

/// A floating point value that represents an angle
@frozen
public struct Angle {

/// The value of the angle in degrees
public let degrees: Float32

/// The value of the angle in radians
public var radians: Float32 {
return degrees * Float32.pi / 180.0
}

/// Creates an instance using the value in radians
/// - Parameter radians: The angle value in radians
public init(radians val: Float32) {
degrees = val / Float32.pi * 180.0
}

/// Creates an instance using the value in degrees
/// - Parameter degrees: The angle value in degrees
public init(degrees val: Float32) {
degrees = val
}

/// Creates an instance using an internal value
/// - Parameter val: The angle value
internal init(_ val: Float32) {
degrees = val
}

// MARK: Constants
public static let zero = Angle(degrees: 0)
public static let pi_6 = Angle(degrees: 30)
public static let pi_4 = Angle(degrees: 45)
public static let pi_3 = Angle(degrees: 60)
public static let pi_2 = Angle(degrees: 90)
public static let pi2_3 = Angle(degrees: 120)
public static let pi = Angle(degrees: 180)
public static let pi3_2 = Angle(degrees: 270)
public static let pi2 = Angle(degrees: 360)
}

extension Angle: CustomStringConvertible, CustomDebugStringConvertible {
public var description: String {
return "\(degrees)°"
}

public var debugDescription: String {
return "\(degrees)°"
}
}

extension Angle: CustomPlaygroundDisplayConvertible {
public var playgroundDescription: Any {
return degrees
}
}

extension Int {
/// Returns the integer value as an angle in degrees
public var degrees: Angle {
return Angle(degrees: Float32(self))
}
}

extension Angle {
// MARK: - operators

// MARK: multiplication (scaling)

/// Multiplies the angle by a scalar value
/// - Parameters:
/// - lhs: The angle to be multiplied
/// - rhs: The scalar value
public static func *=(lhs: inout Angle, rhs: Float32) {
lhs = Angle(lhs.degrees * rhs)
}

/// Multiplies the angle by a scalar value
/// - Parameters:
/// - lhs: The angle to be multiplied
/// - rhs: The scalar value
/// - Returns: The resulting angle after multiplication
public static func *(lhs: Angle, rhs: Float32) -> Angle {
return Angle(lhs.degrees * rhs)
}

/// Multiplies a scalar value by an angle
/// - Parameters:
/// - lhs: The scalar value
/// - rhs: The angle to be multiplied
/// - Returns: The resulting angle after multiplication
public static func *(lhs: Float32, rhs: Angle) -> Angle {
return Angle(rhs.degrees * lhs)
}

// MARK: division (scaling)

/// Divides the angle by a scalar value
/// - Parameters:
/// - lhs: The angle to be divided
/// - rhs: The scalar value
public static func /=(lhs: inout Angle, rhs: Float32) {
lhs = Angle(lhs.degrees / rhs)
}

/// Divides the angle by a scalar value
/// - Parameters:
/// - lhs: The angle to be divided
/// - rhs: The scalar value
/// - Returns: The resulting angle after division
public static func /(lhs: Angle, rhs: Float32) -> Angle {
return Angle(lhs.degrees / rhs)
}

// MARK: addition

/// Adds two angles together
/// - Parameters:
/// - lhs: The first angle
/// - rhs: The second angle
public static func +=(lhs: inout Angle, rhs: Angle) {
lhs = Angle(lhs.degrees + rhs.degrees)
}

/// Adds two angles together
/// - Parameters:
/// - lhs: The first angle
/// - rhs: The second angle
/// - Returns: The resulting angle after addition
public static func +(lhs: Angle, rhs: Angle) -> Angle {
return Angle(lhs.degrees + rhs.degrees)
}

// MARK: subtraction

/// Subtracts one angle from another
/// - Parameters:
/// - lhs: The first angle
/// - rhs: The second angle
public static func -=(lhs: inout Angle, rhs: Angle) {
lhs = Angle(lhs.degrees - rhs.degrees)
}

/// Subtracts one angle from another
/// - Parameters:
/// - lhs: The first angle
/// - rhs: The second angle
/// - Returns: The resulting angle after subtraction
public static func -(lhs: Angle, rhs: Angle) -> Angle {
return Angle(lhs.degrees - rhs.degrees)
}

// MARK: Modulus

/// Returns the remainder of one angle divided by another
/// - Parameters:
/// - lhs: The first angle
/// - rhs: The second angle
/// - Returns: The remainder angle after division
public static func %(lhs: Angle, rhs: Angle) -> Angle {
return Angle(lhs.degrees.truncatingRemainder(dividingBy: rhs.degrees))
}

// MARK: Unary

/// Returns the negation of the angle
/// - Parameter lhs: The angle to be negated
/// - Returns: The negated angle
public static prefix func -(lhs: Angle) -> Angle {
return Angle(-lhs.degrees)
}
}

// MARK: - Equatable

extension Angle: Equatable {
public static func ==(lhs: Angle, rhs: Angle) -> Bool {
return lhs.degrees == rhs.degrees
}
}

// MARK: - Comparable

extension Angle: Comparable {
public static func <(lhs: Angle, rhs: Angle) -> Bool {
return lhs.degrees < rhs.degrees
}

public static func <=(lhs: Angle, rhs: Angle) -> Bool {
return lhs.degrees <= rhs.degrees
}

public static func >(lhs: Angle, rhs: Angle) -> Bool {
return lhs.degrees > rhs.degrees
}

public static func >=(lhs: Angle, rhs: Angle) -> Bool {
return lhs.degrees >= rhs.degrees
}
}

/// Computes the sine and cosine of the given angle
/// - Parameters:
/// - a: The angle
/// - sina: A reference to a variable to store the sine of the angle
/// - cosa: A reference to a variable to store the cosine of the angle
public func sincos(_ a: Angle, _ sina: inout Float, _ cosa: inout Float) {
__sincospif(a.degrees / 180.0, &sina, &cosa)
}

/// Computes the sine and cosine of the given angle
/// - Parameter a: The angle
/// - Returns: A tuple containing the sine and cosine of the angle
public func sincos(_ a: Angle) -> (sin: Float, cos: Float) {
var s: Float = 0.0
var c: Float = 0.0
sincos(a, &s, &c)

return (sin: s, cos: c)
}

/// Computes the sine of the given angle
/// - Parameter a: The angle
/// - Returns: The sine of the angle
public func sin(_ a: Angle) -> Float {
return __sinpif(a.degrees / 180.0)
}

/// Computes the cosine of the given angle
/// - Parameter a: The angle
/// - Returns: The cosine of the angle
public func cos(_ a: Angle) -> Float {
return __cospif(a.degrees / 180.0)
}

/// Computes the tangent of the given angle
/// - Parameter a: The angle
/// - Returns: The tangent of the angle
public func tan(_ a: Angle) -> Float {
return __tanpif(a.degrees / 180.0)
}
26 changes: 26 additions & 0 deletions Sources/SIMDTools/Helpers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/// Clamps a value to the specified range
/// - Parameters:
/// - x: The value to be clamped
/// - min: The minimum value
/// - max: The maximum value
/// - Returns: The clamped value
public func clamp<T>(_ x: T, min: T, max: T) -> T where T: Comparable {
Swift.min(Swift.max(x, min), max)
}

/// Clamps a value to the range [0.0, 1.0]
/// - Parameter x: The value to be clamped
/// - Returns: The clamped value
public func saturate<T>(_ x: T) -> T where T: BinaryFloatingPoint {
clamp(x, min: 0.0, max: 1.0)
}

/// Performs a linear interpolation between two values
/// - Parameters:
/// - a: The start value
/// - b: The end value
/// - t: The interpolant
/// - Returns: A value interpolated from a to b
public func interpolate<T>(a: T, b: T, t: T) -> T where T: BinaryFloatingPoint {
a + (b - a) * t
}
Loading

0 comments on commit ae3be0d

Please sign in to comment.