@swiftbrowser/swift 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Package.swift +200 -9
- package/README.md +7 -9
- package/Sources/AVFoundation/AVFoundation.swift +131 -0
- package/Sources/AVFoundation/Asset.swift +487 -0
- package/Sources/AVFoundation/AudioSession.swift +144 -0
- package/Sources/AVFoundation/CMTime.swift +303 -0
- package/Sources/AVFoundation/Capture.swift +688 -0
- package/Sources/AVFoundation/Player.swift +749 -0
- package/Sources/AVFoundation/PlayerView.swift +117 -0
- package/Sources/AVKit/AVKit.swift +132 -0
- package/Sources/Accelerate/Accelerate.swift +122 -0
- package/Sources/AppIntents/AppIntents.swift +144 -0
- package/Sources/AppIntents/Parameters.swift +220 -0
- package/Sources/AppIntents/Shortcuts.swift +159 -0
- package/Sources/AudioToolbox/AudioToolbox.swift +55 -0
- package/Sources/AuthenticationServices/AuthenticationServices.swift +257 -0
- package/Sources/AuthenticationServices/Authorization.swift +251 -0
- package/Sources/Charts/Charts.swift +0 -4
- package/Sources/Combine/AnyCancellable.swift +65 -0
- package/Sources/Combine/AnyPublisher.swift +148 -0
- package/Sources/Combine/AnySubscriber.swift +230 -0
- package/Sources/Combine/Cancellable.swift +35 -0
- package/Sources/Combine/Codable.swift +29 -0
- package/Sources/Combine/CombineIdentifier.swift +45 -0
- package/Sources/Combine/Concurrency/ConcurrencyHelpers.swift +24 -0
- package/Sources/Combine/Concurrency/Future+Concurrency.swift +136 -0
- package/Sources/Combine/Concurrency/GENERATED-Publisher+Concurrency.swift +397 -0
- package/Sources/Combine/CurrentValueSubject.swift +252 -0
- package/Sources/Combine/CustomCombineIdentifierConvertible.swift +28 -0
- package/Sources/Combine/Future.swift +228 -0
- package/Sources/Combine/GENERATED-RootProtocols.swift +426 -0
- package/Sources/Combine/Helpers/ConduitBase.swift +40 -0
- package/Sources/Combine/Helpers/ConduitList.swift +59 -0
- package/Sources/Combine/Helpers/DebugHook.swift +177 -0
- package/Sources/Combine/Helpers/FilterProducer.swift +174 -0
- package/Sources/Combine/Helpers/Locking.swift +30 -0
- package/Sources/Combine/Helpers/PartialCompletion.swift +26 -0
- package/Sources/Combine/Helpers/ReduceProducer.swift +249 -0
- package/Sources/Combine/Helpers/SubjectSubscriber.swift +96 -0
- package/Sources/Combine/Helpers/SubscriberTap.swift +69 -0
- package/Sources/Combine/Helpers/SubscriptionStatus.swift +33 -0
- package/Sources/Combine/Helpers/SubscriptionTap.swift +33 -0
- package/Sources/Combine/Helpers/Utils.swift +30 -0
- package/Sources/Combine/Helpers/Violations.swift +33 -0
- package/Sources/Combine/ImmediateScheduler.swift +178 -0
- package/Sources/Combine/LICENSE +21 -0
- package/Sources/Combine/NotificationPublisher.swift +48 -0
- package/Sources/Combine/ObjectWillChange.swift +46 -0
- package/Sources/Combine/PassthroughSubject.swift +222 -0
- package/Sources/Combine/Publisher+Subscribe.swift +53 -0
- package/Sources/Combine/Publishers/Deferred.swift +48 -0
- package/Sources/Combine/Publishers/Empty.swift +54 -0
- package/Sources/Combine/Publishers/Fail.swift +42 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Catch.swift +673 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.Encode.swift +388 -0
- package/Sources/Combine/Publishers/GENERATED-Publishers.MapKeyPath.swift +384 -0
- package/Sources/Combine/Publishers/Just.swift +313 -0
- package/Sources/Combine/Publishers/Optional.Publisher.swift +315 -0
- package/Sources/Combine/Publishers/Publishers.AllSatisfy.swift +217 -0
- package/Sources/Combine/Publishers/Publishers.AssertNoFailure.swift +158 -0
- package/Sources/Combine/Publishers/Publishers.Autoconnect.swift +193 -0
- package/Sources/Combine/Publishers/Publishers.Breakpoint.swift +231 -0
- package/Sources/Combine/Publishers/Publishers.Buffer.swift +356 -0
- package/Sources/Combine/Publishers/Publishers.Collect.swift +102 -0
- package/Sources/Combine/Publishers/Publishers.CollectByCount.swift +195 -0
- package/Sources/Combine/Publishers/Publishers.CompactMap.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.Comparison.swift +371 -0
- package/Sources/Combine/Publishers/Publishers.Concatenate.swift +474 -0
- package/Sources/Combine/Publishers/Publishers.Contains.swift +293 -0
- package/Sources/Combine/Publishers/Publishers.Count.swift +87 -0
- package/Sources/Combine/Publishers/Publishers.Debounce.swift +332 -0
- package/Sources/Combine/Publishers/Publishers.Delay.swift +269 -0
- package/Sources/Combine/Publishers/Publishers.Drop.swift +155 -0
- package/Sources/Combine/Publishers/Publishers.DropUntilOutput.swift +283 -0
- package/Sources/Combine/Publishers/Publishers.DropWhile.swift +378 -0
- package/Sources/Combine/Publishers/Publishers.Filter.swift +248 -0
- package/Sources/Combine/Publishers/Publishers.First.swift +261 -0
- package/Sources/Combine/Publishers/Publishers.FlatMap.swift +533 -0
- package/Sources/Combine/Publishers/Publishers.HandleEvents.swift +260 -0
- package/Sources/Combine/Publishers/Publishers.IgnoreOutput.swift +109 -0
- package/Sources/Combine/Publishers/Publishers.Last.swift +252 -0
- package/Sources/Combine/Publishers/Publishers.MakeConnectable.swift +82 -0
- package/Sources/Combine/Publishers/Publishers.Map.swift +351 -0
- package/Sources/Combine/Publishers/Publishers.MapError.swift +140 -0
- package/Sources/Combine/Publishers/Publishers.MeasureInterval.swift +187 -0
- package/Sources/Combine/Publishers/Publishers.Multicast.swift +284 -0
- package/Sources/Combine/Publishers/Publishers.Output.swift +241 -0
- package/Sources/Combine/Publishers/Publishers.PrefixUntilOutput.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.PrefixWhile.swift +176 -0
- package/Sources/Combine/Publishers/Publishers.Print.swift +206 -0
- package/Sources/Combine/Publishers/Publishers.ReceiveOn.swift +227 -0
- package/Sources/Combine/Publishers/Publishers.Reduce.swift +204 -0
- package/Sources/Combine/Publishers/Publishers.RemoveDuplicates.swift +264 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceEmpty.swift +201 -0
- package/Sources/Combine/Publishers/Publishers.ReplaceError.swift +211 -0
- package/Sources/Combine/Publishers/Publishers.Retry.swift +274 -0
- package/Sources/Combine/Publishers/Publishers.Scan.swift +331 -0
- package/Sources/Combine/Publishers/Publishers.Sequence.swift +437 -0
- package/Sources/Combine/Publishers/Publishers.SetFailureType.swift +120 -0
- package/Sources/Combine/Publishers/Publishers.Share.swift +104 -0
- package/Sources/Combine/Publishers/Publishers.SubscribeOn.swift +197 -0
- package/Sources/Combine/Publishers/Publishers.SwitchToLatest.swift +444 -0
- package/Sources/Combine/Publishers/Publishers.Throttle.swift +359 -0
- package/Sources/Combine/Publishers/Publishers.Timeout.swift +301 -0
- package/Sources/Combine/Publishers/Publishers.Zip.swift +720 -0
- package/Sources/Combine/Publishers/Publishers.swift +13 -0
- package/Sources/Combine/Publishers/Record.swift +237 -0
- package/Sources/Combine/Publishers/Result.Publisher.swift +337 -0
- package/Sources/Combine/Result.swift +46 -0
- package/Sources/Combine/Scheduler.swift +89 -0
- package/Sources/Combine/Schedulers.swift +211 -0
- package/Sources/Combine/Subject+Void.swift +17 -0
- package/Sources/Combine/Subscriber+Void.swift +20 -0
- package/Sources/Combine/Subscribers/Subscribers.Assign.swift +175 -0
- package/Sources/Combine/Subscribers/Subscribers.Completion.swift +90 -0
- package/Sources/Combine/Subscribers/Subscribers.Demand.swift +476 -0
- package/Sources/Combine/Subscribers/Subscribers.Sink.swift +206 -0
- package/Sources/Combine/Subscribers/Subscribers.swift +9 -0
- package/Sources/Combine/Subscription.swift +22 -0
- package/Sources/Combine/Subscriptions.swift +42 -0
- package/Sources/Combine/SwiftUIObservation.swift +10 -0
- package/Sources/Combine/_Introspection.swift +107 -0
- package/Sources/CommonCrypto/CommonCrypto.swift +80 -0
- package/Sources/Compression/Compression.swift +365 -0
- package/Sources/Compression/Deflate.swift +407 -0
- package/Sources/Compression/Zlib.swift +179 -0
- package/Sources/CoreFoundationTypes/CoreFoundationTypes.swift +101 -0
- package/Sources/CoreGraphics/CoreGraphics.swift +411 -0
- package/Sources/CoreGraphics/ProjectionTransforms.swift +28 -0
- package/Sources/CoreHaptics/CoreHaptics.swift +399 -0
- package/Sources/CoreImage/CIColor.swift +41 -0
- package/Sources/CoreImage/CIContext.swift +31 -0
- package/Sources/CoreImage/CIDetector.swift +57 -0
- package/Sources/CoreImage/CIFilter.swift +243 -0
- package/Sources/CoreImage/CIFilterBuiltins.swift +136 -0
- package/Sources/CoreImage/CIImage.swift +162 -0
- package/Sources/CoreImage/QRCode.swift +393 -0
- package/Sources/CoreLocation/Coordinate.swift +30 -0
- package/Sources/CoreLocation/Location.swift +65 -0
- package/Sources/CoreML/Evaluation.swift +414 -0
- package/Sources/CoreML/FeatureValue.swift +266 -0
- package/Sources/CoreML/Model.swift +269 -0
- package/Sources/CoreML/MultiArray.swift +92 -0
- package/Sources/CoreML/Specification.swift +233 -0
- package/Sources/CoreText/CoreText.swift +64 -0
- package/Sources/CoreTransferable/CoreTransferable.swift +606 -0
- package/Sources/CryptoKit/ChaChaPoly.swift +258 -0
- package/Sources/CryptoKit/CryptoKit.swift +375 -0
- package/Sources/CryptoKit/Curve25519.swift +317 -0
- package/Sources/CryptoKit/P256.swift +321 -0
- package/Sources/FoundationBridge/AppStorage.swift +165 -0
- package/Sources/FoundationBridge/AssetResources.swift +90 -0
- package/Sources/FoundationBridge/AsyncBytes.swift +128 -0
- package/Sources/FoundationBridge/AsyncImage.swift +116 -0
- package/Sources/FoundationBridge/AttributedStrings.swift +16 -0
- package/Sources/{_FoundationCommon → FoundationBridge}/Bundle.swift +41 -4
- package/Sources/FoundationBridge/CombineExports.swift +8 -0
- package/Sources/FoundationBridge/CoreFoundation.swift +77 -0
- package/Sources/FoundationBridge/Dispatch.swift +458 -0
- package/Sources/FoundationBridge/EnvironmentFoundation.swift +41 -0
- package/Sources/FoundationBridge/FileImporter.swift +128 -0
- package/Sources/FoundationBridge/FileSystem.swift +68 -0
- package/Sources/FoundationBridge/FoundationBridge.swift +24 -72
- package/Sources/FoundationBridge/HostResolution.swift +31 -0
- package/Sources/FoundationBridge/ItemProvider.swift +655 -0
- package/Sources/FoundationBridge/KeyValueObserving.swift +138 -0
- package/Sources/FoundationBridge/Links.swift +127 -0
- package/Sources/FoundationBridge/ListFormatter.swift +32 -0
- package/Sources/FoundationBridge/Localization.swift +149 -0
- package/Sources/FoundationBridge/Locks.swift +50 -0
- package/Sources/FoundationBridge/Markdown.swift +527 -0
- package/Sources/FoundationBridge/MeasurementFormat.swift +95 -0
- package/Sources/FoundationBridge/NotificationCenter.swift +154 -0
- package/Sources/FoundationBridge/OpenURLHandlers.swift +60 -0
- package/Sources/FoundationBridge/Operation.swift +195 -0
- package/Sources/FoundationBridge/ProcessInfo.swift +32 -0
- package/Sources/FoundationBridge/RelativeDateTimeFormatter.swift +136 -0
- package/Sources/FoundationBridge/SceneStorage.swift +78 -0
- package/Sources/FoundationBridge/SecurityExports.swift +8 -0
- package/Sources/FoundationBridge/Selector.swift +226 -0
- package/Sources/FoundationBridge/StringComparators.swift +17 -0
- package/Sources/FoundationBridge/Table.swift +211 -0
- package/Sources/FoundationBridge/TextAttributes.swift +42 -0
- package/Sources/FoundationBridge/Timer.swift +6 -1
- package/Sources/FoundationBridge/URLSession.swift +718 -0
- package/Sources/{_FoundationCommon → FoundationBridge}/UserDefaults.swift +17 -4
- package/Sources/FoundationBridge/WebAuthRedirects.swift +227 -0
- package/Sources/FoundationBridge/WebSocket.swift +187 -0
- package/Sources/FoundationModels/FoundationModels.swift +1098 -0
- package/Sources/ImageIO/GIF.swift +72 -0
- package/Sources/ImageIO/ImageIO.swift +248 -0
- package/Sources/ImageIO/ImageTypes.swift +28 -0
- package/Sources/LinkPresentation/LinkPresentation.swift +249 -0
- package/Sources/LocalAuthentication/LAContext.swift +86 -0
- package/Sources/MapKit/Geometry.swift +223 -0
- package/Sources/MapKit/Map.swift +638 -0
- package/Sources/MapKit/MapView.swift +229 -0
- package/Sources/MobileCoreServices/MobileCoreServices.swift +28 -0
- package/Sources/NaturalLanguage/LanguageIdentifier.swift +317 -0
- package/Sources/NaturalLanguage/NaturalLanguage.swift +135 -0
- package/Sources/OSLog/OSLog.swift +6 -0
- package/Sources/Photos/Photos.swift +572 -0
- package/Sources/PhotosUI/PhotosPicker.swift +248 -0
- package/Sources/PhotosUI/PhotosPickerItem.swift +261 -0
- package/Sources/QuickLook/QuickLook.swift +168 -0
- package/Sources/SafariServices/SafariServices.swift +106 -0
- package/Sources/Security/Security.swift +332 -0
- package/Sources/StoreKit/AppStore.swift +207 -0
- package/Sources/StoreKit/Products.swift +280 -0
- package/Sources/StoreKit/RequestReview.swift +28 -0
- package/Sources/StoreKit/StoreKit1.swift +486 -0
- package/Sources/StoreKit/StoreViews.swift +428 -0
- package/Sources/StoreKit/Transactions.swift +197 -0
- package/Sources/SwiftData/Macros.swift +58 -0
- package/Sources/SwiftData/ModelActor.swift +38 -0
- package/Sources/SwiftData/ModelContainer.swift +129 -0
- package/Sources/SwiftData/ModelContext.swift +451 -0
- package/Sources/SwiftData/PersistentModel.swift +238 -0
- package/Sources/SwiftData/Properties.swift +261 -0
- package/Sources/SwiftData/Query.swift +256 -0
- package/Sources/SwiftData/Schema.swift +192 -0
- package/Sources/SwiftData/Store.swift +146 -0
- package/Sources/SwiftData/StringPredicates.swift +125 -0
- package/Sources/SwiftDataMacros/EntryMacro.swift +82 -0
- package/Sources/SwiftDataMacros/GenerableMacro.swift +183 -0
- package/Sources/SwiftDataMacros/ModelActorMacro.swift +46 -0
- package/Sources/SwiftDataMacros/ModelMacro.swift +260 -0
- package/Sources/SwiftDataMacros/Plugin.swift +18 -0
- package/Sources/SwiftDataMacros/PredicateMacro.swift +1244 -0
- package/Sources/SwiftUI/API/Accessibility.swift +55 -6
- package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
- package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
- package/Sources/SwiftUI/API/Alert.swift +1 -1
- package/Sources/SwiftUI/API/AlignmentGuides.swift +65 -0
- package/Sources/SwiftUI/API/Animation.swift +37 -5
- package/Sources/SwiftUI/API/App.swift +31 -1
- package/Sources/SwiftUI/API/BindingCollections.swift +35 -0
- package/Sources/SwiftUI/API/BindingForEach.swift +27 -0
- package/Sources/SwiftUI/API/Bitmaps.swift +254 -0
- package/Sources/SwiftUI/API/ButtonStyles.swift +96 -0
- package/Sources/SwiftUI/API/Canvas.swift +337 -0
- package/Sources/SwiftUI/API/Color.swift +104 -28
- package/Sources/SwiftUI/API/ColorEffects.swift +52 -0
- package/Sources/SwiftUI/API/ColorPickerAndLabeledContent.swift +138 -0
- package/Sources/SwiftUI/API/ColorSpaces.swift +161 -0
- package/Sources/SwiftUI/API/Commands.swift +106 -0
- package/Sources/SwiftUI/API/ContainerBackground.swift +28 -0
- package/Sources/SwiftUI/API/ContentShape.swift +33 -0
- package/Sources/SwiftUI/API/ContentSizeCategory.swift +35 -0
- package/Sources/SwiftUI/API/ContentUnavailable.swift +101 -0
- package/Sources/SwiftUI/API/Controls.swift +59 -27
- package/Sources/SwiftUI/API/CustomLayout.swift +49 -10
- package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
- package/Sources/SwiftUI/API/Decorations.swift +1 -1
- package/Sources/SwiftUI/API/EditMode.swift +25 -82
- package/Sources/SwiftUI/API/Effects.swift +105 -7
- package/Sources/SwiftUI/API/Entry.swift +8 -0
- package/Sources/SwiftUI/API/Environment.swift +93 -9
- package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
- package/Sources/SwiftUI/API/Focus.swift +11 -3
- package/Sources/SwiftUI/API/Gauge.swift +3 -2
- package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
- package/Sources/SwiftUI/API/GeometryReader.swift +13 -2
- package/Sources/SwiftUI/API/GestureState.swift +65 -0
- package/Sources/SwiftUI/API/Gestures.swift +1 -1
- package/Sources/SwiftUI/API/Glass.swift +127 -0
- package/Sources/SwiftUI/API/Grid.swift +1 -1
- package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
- package/Sources/SwiftUI/API/KeyPress.swift +54 -0
- package/Sources/SwiftUI/API/LabelStyle.swift +13 -6
- package/Sources/SwiftUI/API/Layout.swift +67 -12
- package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
- package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
- package/Sources/SwiftUI/API/Lists.swift +61 -6
- package/Sources/SwiftUI/API/Menu.swift +8 -1
- package/Sources/SwiftUI/API/Modifiers.swift +80 -10
- package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
- package/Sources/SwiftUI/API/Namespace.swift +44 -0
- package/Sources/SwiftUI/API/Navigation.swift +24 -9
- package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
- package/Sources/SwiftUI/API/ObservableObject.swift +16 -2
- package/Sources/SwiftUI/API/Path.swift +543 -0
- package/Sources/SwiftUI/API/Phase8Controls.swift +48 -31
- package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
- package/Sources/SwiftUI/API/Picker.swift +11 -2
- package/Sources/SwiftUI/API/PointerAndKeyboard.swift +77 -0
- package/Sources/SwiftUI/API/Popover.swift +41 -0
- package/Sources/SwiftUI/API/Preferences.swift +262 -0
- package/Sources/SwiftUI/API/Presentation.swift +17 -4
- package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
- package/Sources/SwiftUI/API/Primitives.swift +164 -37
- package/Sources/SwiftUI/API/Publishers.swift +4 -4
- package/Sources/SwiftUI/API/Redaction.swift +75 -0
- package/Sources/SwiftUI/API/RowActions.swift +3 -2
- package/Sources/SwiftUI/API/Scenes.swift +131 -0
- package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
- package/Sources/SwiftUI/API/ScrollTargets.swift +3 -3
- package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
- package/Sources/SwiftUI/API/SectionSupplements.swift +96 -0
- package/Sources/SwiftUI/API/Shape.swift +214 -0
- package/Sources/SwiftUI/API/ShapeStyle.swift +105 -7
- package/Sources/SwiftUI/API/ShapeTrim.swift +78 -0
- package/Sources/SwiftUI/API/Sharing.swift +193 -0
- package/Sources/SwiftUI/API/StackLayouts.swift +199 -0
- package/Sources/SwiftUI/API/State.swift +18 -1
- package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
- package/Sources/SwiftUI/API/SymbolEffects.swift +203 -0
- package/Sources/SwiftUI/API/TabContent.swift +841 -0
- package/Sources/SwiftUI/API/Table.swift +382 -0
- package/Sources/SwiftUI/API/Tabs.swift +148 -4
- package/Sources/SwiftUI/API/Tasks.swift +2 -2
- package/Sources/SwiftUI/API/Text.swift +386 -0
- package/Sources/SwiftUI/API/TextDates.swift +61 -0
- package/Sources/SwiftUI/API/TextDecorations.swift +52 -0
- package/Sources/SwiftUI/API/TextFieldAxis.swift +103 -0
- package/Sources/SwiftUI/API/TextFieldCommit.swift +52 -0
- package/Sources/SwiftUI/API/Toolbar.swift +52 -16
- package/Sources/SwiftUI/API/Transfer.swift +145 -0
- package/Sources/SwiftUI/API/UnevenRoundedRectangle.swift +66 -0
- package/Sources/SwiftUI/API/Video.swift +64 -0
- package/Sources/SwiftUI/API/View.swift +10 -2
- package/Sources/SwiftUI/API/ViewModifier.swift +4 -1
- package/Sources/SwiftUI/API/VisualEffect.swift +74 -1
- package/Sources/SwiftUI/API/Windows.swift +25 -0
- package/Sources/SwiftUI/Charts/Axis.swift +7 -1
- package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
- package/Sources/SwiftUI/Charts/Chart.swift +17 -3
- package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
- package/Sources/SwiftUI/Localization/Localization.swift +498 -0
- package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
- package/Sources/SwiftUI/Runtime/Executor.swift +2 -0
- package/Sources/SwiftUI/Runtime/Exports.swift +37 -1
- package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
- package/Sources/SwiftUI/Runtime/JSON.swift +76 -4
- package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
- package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
- package/Sources/SwiftUI/Runtime/Ops.swift +58 -12
- package/Sources/SwiftUI/Runtime/Reconciler.swift +10 -1
- package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
- package/Sources/SwiftUI/Runtime/Runtime.swift +977 -198
- package/Sources/SwiftUI/Runtime/Sameness.swift +152 -0
- package/Sources/SwiftUI/Runtime/ViewPath.swift +89 -0
- package/Sources/SwiftUI/Runtime/ViewTraits.swift +175 -0
- package/Sources/SwiftUI/Runtime/WebAuthHeadless.swift +49 -0
- package/Sources/Symbols/Symbols.swift +25 -0
- package/Sources/Translation/Translation.swift +423 -0
- package/Sources/UIKit/Activity.swift +213 -0
- package/Sources/UIKit/Alerts.swift +69 -0
- package/Sources/UIKit/AppDelegate.swift +222 -0
- package/Sources/UIKit/Appearance.swift +84 -0
- package/Sources/UIKit/ColorConversions.swift +70 -0
- package/Sources/UIKit/Controls.swift +225 -0
- package/Sources/UIKit/Device.swift +200 -0
- package/Sources/UIKit/Feedback.swift +65 -0
- package/Sources/UIKit/Font.swift +307 -0
- package/Sources/UIKit/Graphics.swift +204 -0
- package/Sources/UIKit/HostingController.swift +185 -0
- package/Sources/UIKit/Identity.swift +24 -0
- package/Sources/UIKit/Introspectable.swift +510 -0
- package/Sources/UIKit/Pasteboard.swift +363 -0
- package/Sources/UIKit/PhotoAlbum.swift +81 -0
- package/Sources/UIKit/RemoteNotifications.swift +15 -0
- package/Sources/UIKit/Representable.swift +288 -0
- package/Sources/UIKit/SafeArea.swift +12 -0
- package/Sources/UIKit/SceneDelegates.swift +132 -0
- package/Sources/UIKit/Scenes.swift +40 -0
- package/Sources/UIKit/ScrollView.swift +157 -0
- package/Sources/UIKit/ShortcutItems.swift +67 -0
- package/Sources/UIKit/SymbolConfiguration.swift +124 -0
- package/Sources/UIKit/TargetAction.swift +123 -0
- package/Sources/UIKit/TextPaste.swift +161 -0
- package/Sources/UIKit/TextView.swift +538 -0
- package/Sources/UIKit/UIKit.swift +292 -0
- package/Sources/UIKit/UIView.swift +855 -0
- package/Sources/UIKit/ViewTranslation.swift +311 -0
- package/Sources/UniformTypeIdentifiers/UTType.swift +196 -0
- package/Sources/UserNotifications/Content.swift +370 -0
- package/Sources/UserNotifications/NotificationCenter.swift +309 -0
- package/Sources/WeatherKit/WeatherKit.swift +228 -0
- package/Sources/WebKit/WebKit.swift +245 -0
- package/Sources/os/os.swift +376 -0
- package/Sources/zlib/zlib.swift +6 -0
- package/index.d.ts +1 -1
- package/index.mjs +2 -2
- package/manifest.d.mts +2 -0
- package/manifest.mjs +39 -0
- package/package.json +5 -3
- package/sync-sources.mjs +21 -7
- package/Sources/FoundationLite/Common.swift +0 -3
- package/Sources/FoundationLite/FoundationLite.swift +0 -171
- package/Sources/FoundationLite/Interaction.swift +0 -146
- package/Sources/FoundationLite/Timer.swift +0 -48
- package/Sources/_FoundationCommon/_FoundationCommon.swift +0 -10
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
// Evaluating a specification: the math of each supported model type, as Core
|
|
2
|
+
// ML defines it (Model.proto and its siblings in apple/coremltools). A
|
|
3
|
+
// pipeline runs its models in order over one set of named values; every other
|
|
4
|
+
// model reads its declared inputs and writes its declared outputs.
|
|
5
|
+
|
|
6
|
+
import Foundation
|
|
7
|
+
|
|
8
|
+
/// A feature value inside the evaluator.
|
|
9
|
+
enum Value: Equatable {
|
|
10
|
+
case int64(Int64)
|
|
11
|
+
case double(Double)
|
|
12
|
+
case string(String)
|
|
13
|
+
case array([Double], shape: [Int])
|
|
14
|
+
case stringDictionary([String: Double])
|
|
15
|
+
case int64Dictionary([Int64: Double])
|
|
16
|
+
|
|
17
|
+
init(_ value: MLFeatureValue) throws {
|
|
18
|
+
switch value.storage {
|
|
19
|
+
case .undefined(let type): throw MLModelError(.featureType, "An undefined \(type) value cannot be evaluated.")
|
|
20
|
+
case .int64(let value): self = .int64(value)
|
|
21
|
+
case .double(let value): self = .double(value)
|
|
22
|
+
case .string(let value): self = .string(value)
|
|
23
|
+
case .multiArray(let value): self = .array(value.values, shape: value.shape.map(\.intValue))
|
|
24
|
+
case .stringDictionary(let value): self = .stringDictionary(value)
|
|
25
|
+
case .int64Dictionary(let value): self = .int64Dictionary(value)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
var featureValue: MLFeatureValue {
|
|
30
|
+
switch self {
|
|
31
|
+
case .int64(let value): MLFeatureValue(int64: value)
|
|
32
|
+
case .double(let value): MLFeatureValue(double: value)
|
|
33
|
+
case .string(let value): MLFeatureValue(string: value)
|
|
34
|
+
case .array(let values, let shape): MLFeatureValue(multiArray: MLMultiArray(values: values, shape: shape))
|
|
35
|
+
case .stringDictionary(let value): MLFeatureValue(_doubles: value)
|
|
36
|
+
case .int64Dictionary(let value): MLFeatureValue(_doubles: value)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// The value as numbers: a scalar is one, an array its elements.
|
|
41
|
+
var numbers: [Double]? {
|
|
42
|
+
switch self {
|
|
43
|
+
case .int64(let value): [Double(value)]
|
|
44
|
+
case .double(let value): [value]
|
|
45
|
+
case .array(let values, _): values
|
|
46
|
+
default: nil
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/// The value as the type a feature declares: integers and doubles convert
|
|
51
|
+
/// into each other, a scalar into a one-element array and back.
|
|
52
|
+
func converted(to feature: Specification.Feature) throws -> Value {
|
|
53
|
+
switch (feature.featureType, self) {
|
|
54
|
+
case (.double, .int64(let value)): return .double(Double(value))
|
|
55
|
+
case (.double, .array(let values, _)) where values.count == 1: return .double(values[0])
|
|
56
|
+
case (.int64, .double(let value)) where value.isFinite: return .int64(Int64(value.rounded(.towardZero)))
|
|
57
|
+
case (.int64, .array(let values, _)) where values.count == 1 && values[0].isFinite: return .int64(Int64(values[0].rounded(.towardZero)))
|
|
58
|
+
case (.multiArray, .double(let value)): return .array([value], shape: [1])
|
|
59
|
+
case (.multiArray, .int64(let value)): return .array([Double(value)], shape: [1])
|
|
60
|
+
case (.double, .double), (.int64, .int64), (.string, .string), (.multiArray, .array), (.dictionary, .stringDictionary), (.dictionary, .int64Dictionary):
|
|
61
|
+
return self
|
|
62
|
+
default:
|
|
63
|
+
throw MLModelError(.featureType, "Feature \(feature.name) is a \(feature.featureType), not \(self.typeName).")
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
var typeName: String {
|
|
68
|
+
switch self {
|
|
69
|
+
case .int64: "an Int64"
|
|
70
|
+
case .double: "a Double"
|
|
71
|
+
case .string: "a String"
|
|
72
|
+
case .array: "an MLMultiArray"
|
|
73
|
+
case .stringDictionary, .int64Dictionary: "a dictionary"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
extension Specification {
|
|
79
|
+
/// Runs the model on `inputs` (by name; an optional input may be missing)
|
|
80
|
+
/// and returns its declared outputs by name.
|
|
81
|
+
func evaluate(_ inputs: [String: Value]) throws -> [String: Value] {
|
|
82
|
+
var results: [String: Value] = [:]
|
|
83
|
+
switch model {
|
|
84
|
+
case .pipeline(let models):
|
|
85
|
+
var values = inputs
|
|
86
|
+
for model in models {
|
|
87
|
+
let stepInputs = values.filter { name, _ in model.description.inputs.contains { $0.name == name } }
|
|
88
|
+
values.merge(try model.evaluate(stepInputs)) { _, new in new }
|
|
89
|
+
}
|
|
90
|
+
for output in description.outputs {
|
|
91
|
+
if let value = values[output.name] { results[output.name] = value }
|
|
92
|
+
}
|
|
93
|
+
return results
|
|
94
|
+
|
|
95
|
+
case .glmRegressor(let weights, let offsets, let transform):
|
|
96
|
+
let x = try vector(inputs)
|
|
97
|
+
let y = try weights.indices.map { row in
|
|
98
|
+
try glmTransform(dot(weights[row], x) + (offsets.indices.contains(row) ? offsets[row] : 0), transform)
|
|
99
|
+
}
|
|
100
|
+
return try regression(y)
|
|
101
|
+
|
|
102
|
+
case .glmClassifier(let weights, let offsets, let transform, let encoding, let labels):
|
|
103
|
+
let x = try vector(inputs)
|
|
104
|
+
let z = weights.indices.map { row in dot(weights[row], x) + (offsets.indices.contains(row) ? offsets[row] : 0) }
|
|
105
|
+
let probabilities: [Double]
|
|
106
|
+
if z.count == 1 {
|
|
107
|
+
// Binary: the second label's probability.
|
|
108
|
+
let p = try glmTransform(z[0], transform)
|
|
109
|
+
probabilities = [1 - p, p]
|
|
110
|
+
} else if encoding == "oneVsRest" {
|
|
111
|
+
let scores = try z.map { try glmTransform($0, transform) }
|
|
112
|
+
let total = scores.reduce(0, +)
|
|
113
|
+
probabilities = scores.map { total > 0 ? $0 / total : 1 / Double(scores.count) }
|
|
114
|
+
} else {
|
|
115
|
+
// Reference class: the first label's score is 0.
|
|
116
|
+
probabilities = softmax([0] + z)
|
|
117
|
+
}
|
|
118
|
+
return try classification(probabilities, labels: labels)
|
|
119
|
+
|
|
120
|
+
case .treeEnsembleRegressor(let ensemble):
|
|
121
|
+
var y = try ensemble.raw(try vector(inputs))
|
|
122
|
+
if ensemble.transform == "logistic" { y = y.map(sigmoid) }
|
|
123
|
+
return try regression(y)
|
|
124
|
+
|
|
125
|
+
case .treeEnsembleClassifier(let ensemble, let labels):
|
|
126
|
+
let raw = try ensemble.raw(try vector(inputs))
|
|
127
|
+
let probabilities: [Double]
|
|
128
|
+
switch ensemble.transform {
|
|
129
|
+
case "softmax":
|
|
130
|
+
probabilities = softmax(raw)
|
|
131
|
+
case "softmaxWithZeroClassReference":
|
|
132
|
+
probabilities = softmax([0] + raw)
|
|
133
|
+
case "logistic":
|
|
134
|
+
probabilities = raw.count == 1 && labels.count == 2 ? [1 - sigmoid(raw[0]), sigmoid(raw[0])] : raw.map(sigmoid)
|
|
135
|
+
default:
|
|
136
|
+
probabilities = raw.count == 1 && labels.count == 2 ? [1 - raw[0], raw[0]] : raw
|
|
137
|
+
}
|
|
138
|
+
return try classification(probabilities, labels: labels)
|
|
139
|
+
|
|
140
|
+
case .featureVectorizer(let columns):
|
|
141
|
+
var x: [Double] = []
|
|
142
|
+
for column in columns {
|
|
143
|
+
guard let value = inputs[column.name] else { throw missing(column.name) }
|
|
144
|
+
switch value {
|
|
145
|
+
case .int64Dictionary(let sparse):
|
|
146
|
+
// A sparse one-hot encoding: index → value.
|
|
147
|
+
var dense = Array(repeating: 0.0, count: column.dimensions)
|
|
148
|
+
for (index, number) in sparse where index >= 0 && Int(index) < dense.count { dense[Int(index)] = number }
|
|
149
|
+
x += dense
|
|
150
|
+
default:
|
|
151
|
+
guard let numbers = value.numbers else { throw MLModelError(.featureType, "Feature \(column.name) is \(value.typeName); a feature vectorizer takes numbers and arrays.") }
|
|
152
|
+
x += numbers
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return try single(.array(x, shape: [x.count]))
|
|
156
|
+
|
|
157
|
+
case .oneHotEncoder(let categories, let sparse, let ignoreUnknown):
|
|
158
|
+
let (name, value) = try onlyInput(inputs)
|
|
159
|
+
let index = categories.index(of: value)
|
|
160
|
+
if index == nil && !ignoreUnknown {
|
|
161
|
+
throw MLModelError(.generic, "\(name) is not one of the categories the one-hot encoder knows.")
|
|
162
|
+
}
|
|
163
|
+
if sparse {
|
|
164
|
+
return try single(.int64Dictionary(index.map { [Int64($0): 1] } ?? [:]))
|
|
165
|
+
}
|
|
166
|
+
var x = Array(repeating: 0.0, count: categories.count)
|
|
167
|
+
if let index { x[index] = 1 }
|
|
168
|
+
return try single(.array(x, shape: [x.count]))
|
|
169
|
+
|
|
170
|
+
case .normalizer(let norm):
|
|
171
|
+
let (name, value) = try onlyInput(inputs)
|
|
172
|
+
guard let x = value.numbers else { throw MLModelError(.featureType, "\(name) is \(value.typeName); a normalizer takes numbers.") }
|
|
173
|
+
let size: Double
|
|
174
|
+
switch norm {
|
|
175
|
+
case "l1": size = x.reduce(0) { $0 + abs($1) }
|
|
176
|
+
case "l2": size = x.reduce(0) { $0 + $1 * $1 }.squareRoot()
|
|
177
|
+
default: size = x.map(abs).max() ?? 0
|
|
178
|
+
}
|
|
179
|
+
let y = size > 0 ? x.map { $0 / size } : x
|
|
180
|
+
return try single(.array(y, shape: [y.count]))
|
|
181
|
+
|
|
182
|
+
case .imputer(let imputed, let replace):
|
|
183
|
+
let name = description.inputs.first?.name ?? ""
|
|
184
|
+
return try single(try impute(inputs[name], imputed, replace))
|
|
185
|
+
|
|
186
|
+
case .scaler(let shift, let scale):
|
|
187
|
+
let (name, value) = try onlyInput(inputs)
|
|
188
|
+
guard let x = value.numbers else { throw MLModelError(.featureType, "\(name) is \(value.typeName); a scaler takes numbers.") }
|
|
189
|
+
let y = x.indices.map { i in
|
|
190
|
+
let s = scale.isEmpty ? 1 : scale[scale.count == 1 ? 0 : min(i, scale.count - 1)]
|
|
191
|
+
let t = shift.isEmpty ? 0 : shift[shift.count == 1 ? 0 : min(i, shift.count - 1)]
|
|
192
|
+
return s * (x[i] + t)
|
|
193
|
+
}
|
|
194
|
+
if case .array = value { return try single(.array(y, shape: [y.count])) }
|
|
195
|
+
return try single(.double(y[0]))
|
|
196
|
+
|
|
197
|
+
case .dictVectorizer(let keys):
|
|
198
|
+
let (name, value) = try onlyInput(inputs)
|
|
199
|
+
var x = Array(repeating: 0.0, count: keys.count)
|
|
200
|
+
switch (keys, value) {
|
|
201
|
+
case (.strings(let keys), .stringDictionary(let dictionary)):
|
|
202
|
+
for (index, key) in keys.enumerated() { x[index] = dictionary[key] ?? 0 }
|
|
203
|
+
case (.int64s(let keys), .int64Dictionary(let dictionary)):
|
|
204
|
+
for (index, key) in keys.enumerated() { x[index] = dictionary[key] ?? 0 }
|
|
205
|
+
default:
|
|
206
|
+
throw MLModelError(.featureType, "\(name) is \(value.typeName), not a dictionary with the vectorizer's key type.")
|
|
207
|
+
}
|
|
208
|
+
return try single(.array(x, shape: [x.count]))
|
|
209
|
+
|
|
210
|
+
case .arrayFeatureExtractor(let indices):
|
|
211
|
+
let (name, value) = try onlyInput(inputs)
|
|
212
|
+
guard let x = value.numbers else { throw MLModelError(.featureType, "\(name) is \(value.typeName); an array feature extractor takes an array.") }
|
|
213
|
+
guard indices.allSatisfy({ $0 >= 0 && $0 < x.count }) else { throw MLModelError(.generic, "An index of \(indices) is outside \(name), which has \(x.count) elements.") }
|
|
214
|
+
let y = indices.map { x[$0] }
|
|
215
|
+
return try single(y.count == 1 && description.outputs.first?.featureType != .multiArray ? .double(y[0]) : .array(y, shape: [y.count]))
|
|
216
|
+
|
|
217
|
+
case .categoricalMapping(let mapping):
|
|
218
|
+
let (name, value) = try onlyInput(inputs)
|
|
219
|
+
switch value {
|
|
220
|
+
case .string(let string):
|
|
221
|
+
guard let map = mapping.stringToInt64 else { throw MLModelError(.featureType, "\(name) is a String; the mapping takes integers.") }
|
|
222
|
+
guard let mapped = map[string] ?? mapping.defaultInt64 else { throw MLModelError(.generic, "\(string) is not in the categorical mapping.") }
|
|
223
|
+
return try single(.int64(mapped))
|
|
224
|
+
default:
|
|
225
|
+
guard let map = mapping.int64ToString, let integer = value.numbers?.first.flatMap({ Int64(exactly: $0) }) else {
|
|
226
|
+
throw MLModelError(.featureType, "\(name) is \(value.typeName); the mapping takes strings.")
|
|
227
|
+
}
|
|
228
|
+
guard let mapped = map[String(integer)] ?? mapping.defaultString else { throw MLModelError(.generic, "\(integer) is not in the categorical mapping.") }
|
|
229
|
+
return try single(.string(mapped))
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
case .identity:
|
|
233
|
+
for (input, output) in zip(description.inputs, description.outputs) {
|
|
234
|
+
if let value = inputs[input.name] { results[output.name] = try value.converted(to: output) }
|
|
235
|
+
}
|
|
236
|
+
return results
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// MARK: Inputs and outputs
|
|
241
|
+
|
|
242
|
+
private func missing(_ name: String) -> MLModelError {
|
|
243
|
+
MLModelError(.featureType, "Feature \(name) is required but not specified.")
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/// The inputs as one vector of numbers, in the order the model declares them.
|
|
247
|
+
private func vector(_ inputs: [String: Value]) throws -> [Double] {
|
|
248
|
+
var x: [Double] = []
|
|
249
|
+
for feature in description.inputs {
|
|
250
|
+
guard let value = inputs[feature.name] else { throw missing(feature.name) }
|
|
251
|
+
guard let numbers = value.numbers else { throw MLModelError(.featureType, "Feature \(feature.name) is \(value.typeName); this model takes numbers.") }
|
|
252
|
+
x += numbers
|
|
253
|
+
}
|
|
254
|
+
return x
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
private func onlyInput(_ inputs: [String: Value]) throws -> (String, Value) {
|
|
258
|
+
guard let name = description.inputs.first?.name else { throw MLModelError(.generic, "The model declares no input.") }
|
|
259
|
+
guard let value = inputs[name] else { throw missing(name) }
|
|
260
|
+
return (name, value)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/// A transform's one output, under the name (and type) the model declares.
|
|
264
|
+
private func single(_ value: Value) throws -> [String: Value] {
|
|
265
|
+
guard let output = description.outputs.first else { return [:] }
|
|
266
|
+
return [output.name: try value.converted(to: output)]
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private func regression(_ y: [Double]) throws -> [String: Value] {
|
|
270
|
+
let name = description.predictedFeatureName ?? description.outputs.first?.name ?? ""
|
|
271
|
+
guard let output = description.outputs.first(where: { $0.name == name }) else { return [:] }
|
|
272
|
+
let value: Value = y.count == 1 && output.featureType != .multiArray ? .double(y[0]) : .array(y, shape: [y.count])
|
|
273
|
+
return [name: try value.converted(to: output)]
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/// The most probable label and, when the model declares it, every label's probability.
|
|
277
|
+
private func classification(_ probabilities: [Double], labels: Labels) throws -> [String: Value] {
|
|
278
|
+
guard probabilities.count == labels.count else {
|
|
279
|
+
throw MLModelError(.generic, "The model computed \(probabilities.count) class probabilities for \(labels.count) labels.")
|
|
280
|
+
}
|
|
281
|
+
var best = 0
|
|
282
|
+
for index in probabilities.indices where probabilities[index] > probabilities[best] { best = index }
|
|
283
|
+
var results: [String: Value] = [:]
|
|
284
|
+
let labelName = description.predictedFeatureName
|
|
285
|
+
?? description.outputs.first(where: { $0.featureType == .string || $0.featureType == .int64 })?.name
|
|
286
|
+
if let labelName { results[labelName] = labels.value(at: best) }
|
|
287
|
+
let probabilitiesName = description.predictedProbabilitiesName
|
|
288
|
+
?? description.outputs.first(where: { $0.featureType == .dictionary })?.name
|
|
289
|
+
if let probabilitiesName, description.outputs.contains(where: { $0.name == probabilitiesName }) {
|
|
290
|
+
switch labels {
|
|
291
|
+
case .strings(let labels):
|
|
292
|
+
results[probabilitiesName] = .stringDictionary(Dictionary(zip(labels, probabilities), uniquingKeysWith: { first, _ in first }))
|
|
293
|
+
case .int64s(let labels):
|
|
294
|
+
results[probabilitiesName] = .int64Dictionary(Dictionary(zip(labels, probabilities), uniquingKeysWith: { first, _ in first }))
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return results
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// MARK: Imputation
|
|
301
|
+
|
|
302
|
+
private func impute(_ value: Value?, _ imputed: Imputed, _ replace: Replace?) throws -> Value {
|
|
303
|
+
if let double = imputed.double {
|
|
304
|
+
guard let value else { return .double(double) }
|
|
305
|
+
guard case .double(let x) = try value.converted(to: Feature(name: "", type: "double")) else { return value }
|
|
306
|
+
return matches(x, replace?.double) ? .double(double) : .double(x)
|
|
307
|
+
}
|
|
308
|
+
if let int64 = imputed.int64 {
|
|
309
|
+
guard let value else { return .int64(int64) }
|
|
310
|
+
guard case .int64(let x) = try value.converted(to: Feature(name: "", type: "int64")) else { return value }
|
|
311
|
+
return replace?.int64 == x ? .int64(int64) : .int64(x)
|
|
312
|
+
}
|
|
313
|
+
if let string = imputed.string {
|
|
314
|
+
guard case .string(let x)? = value else { return .string(string) }
|
|
315
|
+
return x == (replace?.string ?? "") ? .string(string) : .string(x)
|
|
316
|
+
}
|
|
317
|
+
if let doubles = imputed.doubles ?? imputed.int64s?.map(Double.init) {
|
|
318
|
+
guard let x = value?.numbers else { return .array(doubles, shape: [doubles.count]) }
|
|
319
|
+
let missing = imputed.doubles == nil ? replace?.int64.map(Double.init) : replace?.double
|
|
320
|
+
let y = x.indices.map { i in i < doubles.count && matches(x[i], missing) ? doubles[i] : x[i] }
|
|
321
|
+
return .array(y, shape: [y.count])
|
|
322
|
+
}
|
|
323
|
+
if let defaults = imputed.stringDictionary {
|
|
324
|
+
guard case .stringDictionary(let x)? = value else { return .stringDictionary(defaults) }
|
|
325
|
+
return .stringDictionary(defaults.merging(x) { _, given in given })
|
|
326
|
+
}
|
|
327
|
+
if let defaults = imputed.int64Dictionary {
|
|
328
|
+
let typed = Dictionary(uniqueKeysWithValues: defaults.compactMap { key, number in Int64(key).map { ($0, number) } })
|
|
329
|
+
guard case .int64Dictionary(let x)? = value else { return .int64Dictionary(typed) }
|
|
330
|
+
return .int64Dictionary(typed.merging(x) { _, given in given })
|
|
331
|
+
}
|
|
332
|
+
throw MLModelError(.generic, "The imputer has no imputed value.")
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/// Whether `x` is the value to replace: NaN unless the model names another.
|
|
336
|
+
private func matches(_ x: Double, _ replace: Double?) -> Bool {
|
|
337
|
+
guard let replace, !replace.isNaN else { return x.isNaN }
|
|
338
|
+
return x == replace
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
extension Specification.Feature {
|
|
343
|
+
init(name: String, type: String) {
|
|
344
|
+
self.name = name
|
|
345
|
+
self.type = type
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
extension Specification.TreeEnsemble {
|
|
350
|
+
/// The ensemble's raw prediction: the base values plus every tree's leaf values.
|
|
351
|
+
func raw(_ x: [Double]) throws -> [Double] {
|
|
352
|
+
var y = base.count == dimensions ? base : Array(repeating: 0, count: dimensions)
|
|
353
|
+
for tree in trees {
|
|
354
|
+
var node = 0
|
|
355
|
+
while true {
|
|
356
|
+
let behavior = tree.behaviors[node]
|
|
357
|
+
if behavior == 6 {
|
|
358
|
+
for k in tree.leafStarts[node]..<tree.leafStarts[node + 1] { y[tree.leafIndices[k]] += tree.leafValues[k] }
|
|
359
|
+
break
|
|
360
|
+
}
|
|
361
|
+
let feature = tree.features[node]
|
|
362
|
+
guard feature < x.count else {
|
|
363
|
+
throw MLModelError(.generic, "A tree reads feature \(feature) of an input with \(x.count) values.")
|
|
364
|
+
}
|
|
365
|
+
let value = x[feature]
|
|
366
|
+
let threshold = tree.thresholds[node]
|
|
367
|
+
let goesTrue: Bool
|
|
368
|
+
if value.isNaN {
|
|
369
|
+
goesTrue = tree.missingTrue[node]
|
|
370
|
+
} else {
|
|
371
|
+
switch behavior {
|
|
372
|
+
case 0: goesTrue = value <= threshold
|
|
373
|
+
case 1: goesTrue = value < threshold
|
|
374
|
+
case 2: goesTrue = value >= threshold
|
|
375
|
+
case 3: goesTrue = value > threshold
|
|
376
|
+
case 4: goesTrue = value == threshold
|
|
377
|
+
default: goesTrue = value != threshold
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
node = goesTrue ? tree.trueChildren[node] : tree.falseChildren[node]
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return y
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// MARK: Math
|
|
388
|
+
|
|
389
|
+
private func dot(_ w: [Double], _ x: [Double]) -> Double {
|
|
390
|
+
var sum = 0.0
|
|
391
|
+
for i in 0..<min(w.count, x.count) { sum += w[i] * x[i] }
|
|
392
|
+
return sum
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
func sigmoid(_ z: Double) -> Double { 1 / (1 + exp(-z)) }
|
|
396
|
+
|
|
397
|
+
/// The standard normal distribution function, Φ.
|
|
398
|
+
func probit(_ z: Double) -> Double { 0.5 * erfc(-z / 2.0.squareRoot()) }
|
|
399
|
+
|
|
400
|
+
private func glmTransform(_ z: Double, _ transform: String) throws -> Double {
|
|
401
|
+
switch transform {
|
|
402
|
+
case "none": z
|
|
403
|
+
case "logit": sigmoid(z)
|
|
404
|
+
case "probit": probit(z)
|
|
405
|
+
default: throw MLModelError(.generic, "Unknown GLM transform \(transform).")
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
func softmax(_ z: [Double]) -> [Double] {
|
|
410
|
+
let top = z.max() ?? 0
|
|
411
|
+
let e = z.map { exp($0 - top) }
|
|
412
|
+
let total = e.reduce(0, +)
|
|
413
|
+
return e.map { $0 / total }
|
|
414
|
+
}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
// Core ML's feature values and the providers that carry them in and out of a
|
|
2
|
+
// model, as far as tabular models use them: integers, doubles, strings,
|
|
3
|
+
// multiarrays and dictionaries. Images and sequences have no counterpart.
|
|
4
|
+
|
|
5
|
+
import Foundation
|
|
6
|
+
|
|
7
|
+
/// The type of a feature, with Core ML's raw values.
|
|
8
|
+
public enum MLFeatureType: Int, Sendable, CustomStringConvertible {
|
|
9
|
+
case invalid = 0
|
|
10
|
+
case int64 = 1
|
|
11
|
+
case double = 2
|
|
12
|
+
case string = 3
|
|
13
|
+
case image = 4
|
|
14
|
+
case multiArray = 5
|
|
15
|
+
case dictionary = 6
|
|
16
|
+
case sequence = 7
|
|
17
|
+
case state = 8
|
|
18
|
+
|
|
19
|
+
public var description: String {
|
|
20
|
+
switch self {
|
|
21
|
+
case .invalid: "Invalid"
|
|
22
|
+
case .int64: "Int64"
|
|
23
|
+
case .double: "Double"
|
|
24
|
+
case .string: "String"
|
|
25
|
+
case .image: "Image"
|
|
26
|
+
case .multiArray: "MultiArray"
|
|
27
|
+
case .dictionary: "Dictionary"
|
|
28
|
+
case .sequence: "Sequence"
|
|
29
|
+
case .state: "State"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// One value of a feature: what a model takes and returns.
|
|
35
|
+
public final class MLFeatureValue: @unchecked Sendable, CustomStringConvertible {
|
|
36
|
+
enum Storage {
|
|
37
|
+
case undefined(MLFeatureType)
|
|
38
|
+
case int64(Int64)
|
|
39
|
+
case double(Double)
|
|
40
|
+
case string(String)
|
|
41
|
+
case multiArray(MLMultiArray)
|
|
42
|
+
case stringDictionary([String: Double])
|
|
43
|
+
case int64Dictionary([Int64: Double])
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
let storage: Storage
|
|
47
|
+
|
|
48
|
+
init(storage: Storage) { self.storage = storage }
|
|
49
|
+
|
|
50
|
+
public convenience init(int64 value: Int64) { self.init(storage: .int64(value)) }
|
|
51
|
+
public convenience init(double value: Double) { self.init(storage: .double(value)) }
|
|
52
|
+
public convenience init(string value: String) { self.init(storage: .string(value)) }
|
|
53
|
+
public convenience init(multiArray value: MLMultiArray) { self.init(storage: .multiArray(value)) }
|
|
54
|
+
/// A missing value of a type, for an optional input.
|
|
55
|
+
public convenience init(undefined type: MLFeatureType) { self.init(storage: .undefined(type)) }
|
|
56
|
+
|
|
57
|
+
/// A dictionary of `String` or integer keys to numbers.
|
|
58
|
+
public convenience init(dictionary value: [AnyHashable: NSNumber]) throws {
|
|
59
|
+
var strings: [String: Double] = [:]
|
|
60
|
+
var integers: [Int64: Double] = [:]
|
|
61
|
+
for (key, number) in value {
|
|
62
|
+
if let key = key.base as? String {
|
|
63
|
+
strings[key] = number.doubleValue
|
|
64
|
+
} else if let key = _int64(key.base) {
|
|
65
|
+
integers[key] = number.doubleValue
|
|
66
|
+
} else {
|
|
67
|
+
throw MLModelError(.featureType, "Dictionary keys must be strings or integers, not \(Swift.type(of: key.base)).")
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if !strings.isEmpty && !integers.isEmpty {
|
|
71
|
+
throw MLModelError(.featureType, "Dictionary keys must be all strings or all integers.")
|
|
72
|
+
}
|
|
73
|
+
self.init(storage: integers.isEmpty ? .stringDictionary(strings) : .int64Dictionary(integers))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// The generated model classes' dictionary inputs and outputs (`[String : Double]`, `[Int64 : Double]`).
|
|
77
|
+
public convenience init<Key: Hashable>(_doubles value: [Key: Double]) {
|
|
78
|
+
if let strings = value as? [String: Double] {
|
|
79
|
+
self.init(storage: .stringDictionary(strings))
|
|
80
|
+
} else {
|
|
81
|
+
var integers: [Int64: Double] = [:]
|
|
82
|
+
for (key, number) in value { integers[_int64(key) ?? 0] = number }
|
|
83
|
+
self.init(storage: .int64Dictionary(integers))
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
public var type: MLFeatureType {
|
|
88
|
+
switch storage {
|
|
89
|
+
case .undefined(let type): type
|
|
90
|
+
case .int64: .int64
|
|
91
|
+
case .double: .double
|
|
92
|
+
case .string: .string
|
|
93
|
+
case .multiArray: .multiArray
|
|
94
|
+
case .stringDictionary, .int64Dictionary: .dictionary
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public var isUndefined: Bool {
|
|
99
|
+
if case .undefined = storage { return true }
|
|
100
|
+
return false
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/// The value as an integer (0 when it is not a number).
|
|
104
|
+
public var int64Value: Int64 {
|
|
105
|
+
switch storage {
|
|
106
|
+
case .int64(let value): value
|
|
107
|
+
case .double(let value): value.isFinite ? Int64(value) : 0
|
|
108
|
+
default: 0
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/// The value as a double (0 when it is not a number).
|
|
113
|
+
public var doubleValue: Double {
|
|
114
|
+
switch storage {
|
|
115
|
+
case .double(let value): value
|
|
116
|
+
case .int64(let value): Double(value)
|
|
117
|
+
default: 0
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/// The value as a string ("" when it is not one).
|
|
122
|
+
public var stringValue: String {
|
|
123
|
+
if case .string(let value) = storage { return value }
|
|
124
|
+
return ""
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public var multiArrayValue: MLMultiArray? {
|
|
128
|
+
if case .multiArray(let value) = storage { return value }
|
|
129
|
+
return nil
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/// The value as a dictionary of `String` or `Int64` keys to numbers (empty when it is not one).
|
|
133
|
+
public var dictionaryValue: [AnyHashable: NSNumber] {
|
|
134
|
+
switch storage {
|
|
135
|
+
case .stringDictionary(let value):
|
|
136
|
+
return Dictionary(uniqueKeysWithValues: value.map { (AnyHashable($0.key), NSNumber(value: $0.value)) })
|
|
137
|
+
case .int64Dictionary(let value):
|
|
138
|
+
return Dictionary(uniqueKeysWithValues: value.map { (AnyHashable($0.key), NSNumber(value: $0.value)) })
|
|
139
|
+
default:
|
|
140
|
+
return [:]
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/// The dictionary with typed keys, for the generated model classes' outputs.
|
|
145
|
+
public func _doubles<Key: Hashable>(keyedBy: Key.Type) -> [Key: Double] {
|
|
146
|
+
switch storage {
|
|
147
|
+
case .stringDictionary(let value):
|
|
148
|
+
return value as? [Key: Double] ?? [:]
|
|
149
|
+
case .int64Dictionary(let value):
|
|
150
|
+
return value as? [Key: Double] ?? [:]
|
|
151
|
+
default:
|
|
152
|
+
return [:]
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
public func isEqual(to other: MLFeatureValue) -> Bool {
|
|
157
|
+
switch (storage, other.storage) {
|
|
158
|
+
case (.undefined(let a), .undefined(let b)): a == b
|
|
159
|
+
case (.int64(let a), .int64(let b)): a == b
|
|
160
|
+
case (.double(let a), .double(let b)): a == b
|
|
161
|
+
case (.string(let a), .string(let b)): a == b
|
|
162
|
+
case (.multiArray(let a), .multiArray(let b)): a.shape == b.shape && a.values == b.values
|
|
163
|
+
case (.stringDictionary(let a), .stringDictionary(let b)): a == b
|
|
164
|
+
case (.int64Dictionary(let a), .int64Dictionary(let b)): a == b
|
|
165
|
+
default: false
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
public var description: String {
|
|
170
|
+
switch storage {
|
|
171
|
+
case .undefined(let type): "Undefined \(type)"
|
|
172
|
+
case .int64(let value): "\(value) : Int64"
|
|
173
|
+
case .double(let value): "\(value) : Double"
|
|
174
|
+
case .string(let value): "\(value) : String"
|
|
175
|
+
case .multiArray(let value): "\(value) : MultiArray"
|
|
176
|
+
case .stringDictionary(let value): "\(value) : Dictionary"
|
|
177
|
+
case .int64Dictionary(let value): "\(value) : Dictionary"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/// An integer key of any width as `Int64`.
|
|
183
|
+
func _int64(_ value: Any) -> Int64? {
|
|
184
|
+
switch value {
|
|
185
|
+
case let value as Int64: value
|
|
186
|
+
case let value as Int: Int64(value)
|
|
187
|
+
case let value as Int32: Int64(value)
|
|
188
|
+
case let value as Int16: Int64(value)
|
|
189
|
+
case let value as Int8: Int64(value)
|
|
190
|
+
case let value as UInt: Int64(exactly: value)
|
|
191
|
+
case let value as UInt32: Int64(value)
|
|
192
|
+
case let value as NSNumber: value.int64Value
|
|
193
|
+
default: nil
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/// Named feature values: a model's input or output.
|
|
198
|
+
public protocol MLFeatureProvider: AnyObject {
|
|
199
|
+
var featureNames: Set<String> { get }
|
|
200
|
+
func featureValue(for featureName: String) -> MLFeatureValue?
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/// A feature provider backed by a dictionary.
|
|
204
|
+
public final class MLDictionaryFeatureProvider: MLFeatureProvider, @unchecked Sendable {
|
|
205
|
+
public let dictionary: [String: MLFeatureValue]
|
|
206
|
+
|
|
207
|
+
/// Values may be `MLFeatureValue`s, numbers, strings, `MLMultiArray`s or dictionaries of numbers.
|
|
208
|
+
public init(dictionary: [String: Any]) throws {
|
|
209
|
+
var values: [String: MLFeatureValue] = [:]
|
|
210
|
+
for (name, value) in dictionary {
|
|
211
|
+
guard let featureValue = MLDictionaryFeatureProvider.featureValue(value) else {
|
|
212
|
+
throw MLModelError(.featureType, "The value of \(name) (\(Swift.type(of: value))) cannot be a feature value.")
|
|
213
|
+
}
|
|
214
|
+
values[name] = featureValue
|
|
215
|
+
}
|
|
216
|
+
self.dictionary = values
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
static func featureValue(_ value: Any) -> MLFeatureValue? {
|
|
220
|
+
switch value {
|
|
221
|
+
case let value as MLFeatureValue: value
|
|
222
|
+
case let value as Double: MLFeatureValue(double: value)
|
|
223
|
+
case let value as Float: MLFeatureValue(double: Double(value))
|
|
224
|
+
case let value as String: MLFeatureValue(string: value)
|
|
225
|
+
case let value as MLMultiArray: MLFeatureValue(multiArray: value)
|
|
226
|
+
case let value as [String: Double]: MLFeatureValue(_doubles: value)
|
|
227
|
+
case let value as [Int64: Double]: MLFeatureValue(_doubles: value)
|
|
228
|
+
case let value as [Int: Double]: MLFeatureValue(_doubles: Dictionary(uniqueKeysWithValues: value.map { (Int64($0.key), $0.value) }))
|
|
229
|
+
case let value as [AnyHashable: NSNumber]: try? MLFeatureValue(dictionary: value)
|
|
230
|
+
case let value as NSNumber: MLFeatureValue(double: value.doubleValue)
|
|
231
|
+
default: _int64(value).map { MLFeatureValue(int64: $0) }
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
public var featureNames: Set<String> { Set(dictionary.keys) }
|
|
236
|
+
|
|
237
|
+
public func featureValue(for featureName: String) -> MLFeatureValue? { dictionary[featureName] }
|
|
238
|
+
|
|
239
|
+
public subscript(featureName: String) -> MLFeatureValue? { dictionary[featureName] }
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/// Several inputs (or outputs) of a model, for batch predictions.
|
|
243
|
+
public protocol MLBatchProvider: AnyObject {
|
|
244
|
+
var count: Int { get }
|
|
245
|
+
func features(at index: Int) -> MLFeatureProvider
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
public final class MLArrayBatchProvider: MLBatchProvider, @unchecked Sendable {
|
|
249
|
+
public let array: [MLFeatureProvider]
|
|
250
|
+
|
|
251
|
+
public init(array: [MLFeatureProvider]) { self.array = array }
|
|
252
|
+
|
|
253
|
+
/// One provider per index of the value lists, which must have the same length.
|
|
254
|
+
public init(dictionary: [String: [Any]]) throws {
|
|
255
|
+
let counts = Set(dictionary.values.map(\.count))
|
|
256
|
+
guard counts.count <= 1 else { throw MLModelError(.generic, "The feature value lists have different lengths.") }
|
|
257
|
+
let count = counts.first ?? 0
|
|
258
|
+
array = try (0..<count).map { index in
|
|
259
|
+
try MLDictionaryFeatureProvider(dictionary: dictionary.mapValues { $0[index] })
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
public var count: Int { array.count }
|
|
264
|
+
|
|
265
|
+
public func features(at index: Int) -> MLFeatureProvider { array[index] }
|
|
266
|
+
}
|