Initial commit. I can successfully create random tensor.
This commit is contained in:
20
lib/main.dart
Normal file
20
lib/main.dart
Normal file
@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'src/app.dart';
|
||||
import 'src/settings/settings_controller.dart';
|
||||
import 'src/settings/settings_service.dart';
|
||||
|
||||
void main() async {
|
||||
// Set up the SettingsController, which will glue user settings to multiple
|
||||
// Flutter Widgets.
|
||||
final settingsController = SettingsController(SettingsService());
|
||||
|
||||
// Load the user's preferred theme while the splash screen is displayed.
|
||||
// This prevents a sudden theme change when the app is first displayed.
|
||||
await settingsController.loadSettings();
|
||||
|
||||
// Run the app and pass in the SettingsController. The app listens to the
|
||||
// SettingsController for changes, then passes it further down to the
|
||||
// SettingsView.
|
||||
runApp(MyApp(settingsController: settingsController));
|
||||
}
|
85
lib/src/app.dart
Normal file
85
lib/src/app.dart
Normal file
@ -0,0 +1,85 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
|
||||
import 'sample_feature/sample_item_details_view.dart';
|
||||
import 'sample_feature/sample_item_list_view.dart';
|
||||
import 'settings/settings_controller.dart';
|
||||
import 'settings/settings_view.dart';
|
||||
|
||||
/// The Widget that configures your application.
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({
|
||||
super.key,
|
||||
required this.settingsController,
|
||||
});
|
||||
|
||||
final SettingsController settingsController;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// Glue the SettingsController to the MaterialApp.
|
||||
//
|
||||
// The ListenableBuilder Widget listens to the SettingsController for changes.
|
||||
// Whenever the user updates their settings, the MaterialApp is rebuilt.
|
||||
return ListenableBuilder(
|
||||
listenable: settingsController,
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
return MaterialApp(
|
||||
// Providing a restorationScopeId allows the Navigator built by the
|
||||
// MaterialApp to restore the navigation stack when a user leaves and
|
||||
// returns to the app after it has been killed while running in the
|
||||
// background.
|
||||
restorationScopeId: 'app',
|
||||
|
||||
// Provide the generated AppLocalizations to the MaterialApp. This
|
||||
// allows descendant Widgets to display the correct translations
|
||||
// depending on the user's locale.
|
||||
localizationsDelegates: const [
|
||||
AppLocalizations.delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: const [
|
||||
Locale('en', ''), // English, no country code
|
||||
],
|
||||
|
||||
// Use AppLocalizations to configure the correct application title
|
||||
// depending on the user's locale.
|
||||
//
|
||||
// The appTitle is defined in .arb files found in the localization
|
||||
// directory.
|
||||
onGenerateTitle: (BuildContext context) =>
|
||||
AppLocalizations.of(context)!.appTitle,
|
||||
|
||||
// Define a light and dark color theme. Then, read the user's
|
||||
// preferred ThemeMode (light, dark, or system default) from the
|
||||
// SettingsController to display the correct theme.
|
||||
theme: ThemeData(),
|
||||
darkTheme: ThemeData.dark(),
|
||||
themeMode: settingsController.themeMode,
|
||||
|
||||
// Define a function to handle named routes in order to support
|
||||
// Flutter web url navigation and deep linking.
|
||||
onGenerateRoute: (RouteSettings routeSettings) {
|
||||
return MaterialPageRoute<void>(
|
||||
settings: routeSettings,
|
||||
builder: (BuildContext context) {
|
||||
switch (routeSettings.name) {
|
||||
case SettingsView.routeName:
|
||||
return SettingsView(controller: settingsController);
|
||||
case SampleItemDetailsView.routeName:
|
||||
return const SampleItemDetailsView();
|
||||
case SampleItemListView.routeName:
|
||||
default:
|
||||
return const SampleItemListView();
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
6
lib/src/localization/app_en.arb
Normal file
6
lib/src/localization/app_en.arb
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"appTitle": "archimedes_test",
|
||||
"@appTitle": {
|
||||
"description": "The title of the application"
|
||||
}
|
||||
}
|
6
lib/src/sample_feature/sample_item.dart
Normal file
6
lib/src/sample_feature/sample_item.dart
Normal file
@ -0,0 +1,6 @@
|
||||
/// A placeholder class that represents an entity or model.
|
||||
class SampleItem {
|
||||
const SampleItem(this.id);
|
||||
|
||||
final int id;
|
||||
}
|
20
lib/src/sample_feature/sample_item_details_view.dart
Normal file
20
lib/src/sample_feature/sample_item_details_view.dart
Normal file
@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Displays detailed information about a SampleItem.
|
||||
class SampleItemDetailsView extends StatelessWidget {
|
||||
const SampleItemDetailsView({super.key});
|
||||
|
||||
static const routeName = '/sample_item';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Item Details'),
|
||||
),
|
||||
body: const Center(
|
||||
child: Text('More Information Here'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
71
lib/src/sample_feature/sample_item_list_view.dart
Normal file
71
lib/src/sample_feature/sample_item_list_view.dart
Normal file
@ -0,0 +1,71 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../settings/settings_view.dart';
|
||||
import 'sample_item.dart';
|
||||
import 'sample_item_details_view.dart';
|
||||
|
||||
/// Displays a list of SampleItems.
|
||||
class SampleItemListView extends StatelessWidget {
|
||||
const SampleItemListView({
|
||||
super.key,
|
||||
this.items = const [SampleItem(1), SampleItem(2), SampleItem(3)],
|
||||
});
|
||||
|
||||
static const routeName = '/';
|
||||
|
||||
final List<SampleItem> items;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Sample Items'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.settings),
|
||||
onPressed: () {
|
||||
// Navigate to the settings page. If the user leaves and returns
|
||||
// to the app after it has been killed while running in the
|
||||
// background, the navigation stack is restored.
|
||||
Navigator.restorablePushNamed(context, SettingsView.routeName);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// To work with lists that may contain a large number of items, it’s best
|
||||
// to use the ListView.builder constructor.
|
||||
//
|
||||
// In contrast to the default ListView constructor, which requires
|
||||
// building all Widgets up front, the ListView.builder constructor lazily
|
||||
// builds Widgets as they’re scrolled into view.
|
||||
body: ListView.builder(
|
||||
// Providing a restorationId allows the ListView to restore the
|
||||
// scroll position when a user leaves and returns to the app after it
|
||||
// has been killed while running in the background.
|
||||
restorationId: 'sampleItemListView',
|
||||
itemCount: items.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final item = items[index];
|
||||
|
||||
return ListTile(
|
||||
title: Text('SampleItem ${item.id}'),
|
||||
leading: const CircleAvatar(
|
||||
// Display the Flutter Logo image asset.
|
||||
foregroundImage: AssetImage('assets/images/flutter_logo.png'),
|
||||
),
|
||||
onTap: () {
|
||||
// Navigate to the details page. If the user leaves and returns to
|
||||
// the app after it has been killed while running in the
|
||||
// background, the navigation stack is restored.
|
||||
Navigator.restorablePushNamed(
|
||||
context,
|
||||
SampleItemDetailsView.routeName,
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
50
lib/src/settings/settings_controller.dart
Normal file
50
lib/src/settings/settings_controller.dart
Normal file
@ -0,0 +1,50 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'settings_service.dart';
|
||||
|
||||
/// A class that many Widgets can interact with to read user settings, update
|
||||
/// user settings, or listen to user settings changes.
|
||||
///
|
||||
/// Controllers glue Data Services to Flutter Widgets. The SettingsController
|
||||
/// uses the SettingsService to store and retrieve user settings.
|
||||
class SettingsController with ChangeNotifier {
|
||||
SettingsController(this._settingsService);
|
||||
|
||||
// Make SettingsService a private variable so it is not used directly.
|
||||
final SettingsService _settingsService;
|
||||
|
||||
// Make ThemeMode a private variable so it is not updated directly without
|
||||
// also persisting the changes with the SettingsService.
|
||||
late ThemeMode _themeMode;
|
||||
|
||||
// Allow Widgets to read the user's preferred ThemeMode.
|
||||
ThemeMode get themeMode => _themeMode;
|
||||
|
||||
/// Load the user's settings from the SettingsService. It may load from a
|
||||
/// local database or the internet. The controller only knows it can load the
|
||||
/// settings from the service.
|
||||
Future<void> loadSettings() async {
|
||||
_themeMode = await _settingsService.themeMode();
|
||||
|
||||
// Important! Inform listeners a change has occurred.
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Update and persist the ThemeMode based on the user's selection.
|
||||
Future<void> updateThemeMode(ThemeMode? newThemeMode) async {
|
||||
if (newThemeMode == null) return;
|
||||
|
||||
// Do not perform any work if new and old ThemeMode are identical
|
||||
if (newThemeMode == _themeMode) return;
|
||||
|
||||
// Otherwise, store the new ThemeMode in memory
|
||||
_themeMode = newThemeMode;
|
||||
|
||||
// Important! Inform listeners a change has occurred.
|
||||
notifyListeners();
|
||||
|
||||
// Persist the changes to a local database or the internet using the
|
||||
// SettingService.
|
||||
await _settingsService.updateThemeMode(newThemeMode);
|
||||
}
|
||||
}
|
17
lib/src/settings/settings_service.dart
Normal file
17
lib/src/settings/settings_service.dart
Normal file
@ -0,0 +1,17 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// A service that stores and retrieves user settings.
|
||||
///
|
||||
/// By default, this class does not persist user settings. If you'd like to
|
||||
/// persist the user settings locally, use the shared_preferences package. If
|
||||
/// you'd like to store settings on a web server, use the http package.
|
||||
class SettingsService {
|
||||
/// Loads the User's preferred ThemeMode from local or remote storage.
|
||||
Future<ThemeMode> themeMode() async => ThemeMode.system;
|
||||
|
||||
/// Persists the user's preferred ThemeMode to local or remote storage.
|
||||
Future<void> updateThemeMode(ThemeMode theme) async {
|
||||
// Use the shared_preferences package to persist settings locally or the
|
||||
// http package to persist settings over the network.
|
||||
}
|
||||
}
|
51
lib/src/settings/settings_view.dart
Normal file
51
lib/src/settings/settings_view.dart
Normal file
@ -0,0 +1,51 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'settings_controller.dart';
|
||||
|
||||
/// Displays the various settings that can be customized by the user.
|
||||
///
|
||||
/// When a user changes a setting, the SettingsController is updated and
|
||||
/// Widgets that listen to the SettingsController are rebuilt.
|
||||
class SettingsView extends StatelessWidget {
|
||||
const SettingsView({super.key, required this.controller});
|
||||
|
||||
static const routeName = '/settings';
|
||||
|
||||
final SettingsController controller;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Settings'),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
// Glue the SettingsController to the theme selection DropdownButton.
|
||||
//
|
||||
// When a user selects a theme from the dropdown list, the
|
||||
// SettingsController is updated, which rebuilds the MaterialApp.
|
||||
child: DropdownButton<ThemeMode>(
|
||||
// Read the selected themeMode from the controller
|
||||
value: controller.themeMode,
|
||||
// Call the updateThemeMode method any time the user selects a theme.
|
||||
onChanged: controller.updateThemeMode,
|
||||
items: const [
|
||||
DropdownMenuItem(
|
||||
value: ThemeMode.system,
|
||||
child: Text('System Theme'),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: ThemeMode.light,
|
||||
child: Text('Light Theme'),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: ThemeMode.dark,
|
||||
child: Text('Dark Theme'),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
40
lib/src/splat/camera.dart
Normal file
40
lib/src/splat/camera.dart
Normal file
@ -0,0 +1,40 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:archimedes_test/src/splat/tensor.dart';
|
||||
import 'package:camera/camera.dart';
|
||||
|
||||
class Camera {
|
||||
int id = -1;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
double fx = 0;
|
||||
double fy = 0;
|
||||
double cx = 0;
|
||||
double cy = 0;
|
||||
double k1 = 0;
|
||||
double k2 = 0;
|
||||
double k3 = 0;
|
||||
double p1 = 0;
|
||||
double p2 = 0;
|
||||
|
||||
ByteBuffer? image;
|
||||
Tensor? camToWorld;
|
||||
|
||||
List<List<double>> getIntrinsicsMatrix() {
|
||||
return [
|
||||
[fx, 0.0, cx],
|
||||
[0.0, fy, cy],
|
||||
[0.0, 0.0, 1.0]
|
||||
];
|
||||
}
|
||||
|
||||
Future<CameraDescription?> getFrontCameraDescription() async {
|
||||
List<CameraDescription> cameras = await availableCameras();
|
||||
for (CameraDescription cd in cameras) {
|
||||
if (cd.lensDirection == CameraLensDirection.front) {
|
||||
return cd;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
5
lib/src/splat/input_data.dart
Normal file
5
lib/src/splat/input_data.dart
Normal file
@ -0,0 +1,5 @@
|
||||
import 'package:archimedes_test/src/splat/camera.dart';
|
||||
|
||||
class InputData {
|
||||
List<Camera>? cameras;
|
||||
}
|
1
lib/src/splat/listutil.dart
Normal file
1
lib/src/splat/listutil.dart
Normal file
@ -0,0 +1 @@
|
||||
|
48
lib/src/splat/model.dart
Normal file
48
lib/src/splat/model.dart
Normal file
@ -0,0 +1,48 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:archimedes_test/src/splat/tensor.dart';
|
||||
|
||||
double minus(double i) {
|
||||
return 1 - i;
|
||||
}
|
||||
|
||||
Tensor randomQuantTensor(int n) {
|
||||
Tensor u = Tensor.random([n]);
|
||||
Tensor v = Tensor.random([n]);
|
||||
Tensor w = Tensor.random([n]);
|
||||
|
||||
Tensor a1 = u.each((f, _, __) {
|
||||
return sin(2 * pi * f);
|
||||
});
|
||||
Tensor a2 = u.each((f, _, __) {
|
||||
return sqrt(1 - f);
|
||||
});
|
||||
Tensor a = a1 * a2;
|
||||
|
||||
Tensor b1 = v.each((f, _, __) {
|
||||
return cos(2 * pi * f);
|
||||
});
|
||||
Tensor b2 = v.each((f, _, __) {
|
||||
return sqrt(1 - f);
|
||||
});
|
||||
|
||||
Tensor b = b1 * b2;
|
||||
|
||||
Tensor c1 = u.each((f, _, __) {
|
||||
return sqrt(f);
|
||||
});
|
||||
Tensor c2 = w.each((f, _, __) {
|
||||
return sin(2 * pi * f);
|
||||
});
|
||||
Tensor c = c1 * c2;
|
||||
|
||||
Tensor d1 = u.each((f, _, __) {
|
||||
return sqrt(f);
|
||||
});
|
||||
Tensor d2 = w.each((f, _, __) {
|
||||
return cos(2 * pi * f);
|
||||
});
|
||||
Tensor d = d1 * d2;
|
||||
|
||||
return Tensor.stack(Tensor([a[0], b[0], c[0], d[0]]));
|
||||
}
|
8
lib/src/splat/points.dart
Normal file
8
lib/src/splat/points.dart
Normal file
@ -0,0 +1,8 @@
|
||||
import 'package:archimedes_test/src/splat/tensor.dart';
|
||||
|
||||
class Points {
|
||||
Tensor xyz;
|
||||
Tensor rgb;
|
||||
|
||||
Points(this.xyz, this.rgb);
|
||||
}
|
85
lib/src/splat/tensor.dart
Normal file
85
lib/src/splat/tensor.dart
Normal file
@ -0,0 +1,85 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
class Tensor extends DelegatingList<DelegatingList<double>> {
|
||||
Tensor(super.base);
|
||||
|
||||
Tensor each(Function(double, int, int) f) {
|
||||
Tensor other = Tensor([]);
|
||||
for (int j = 0; j < length; ++j) {
|
||||
other[j] = const DelegatingList([]);
|
||||
for (int k = 0; k < this[j].length; ++k) {
|
||||
other[j][k] = f(this[j][k], j, k);
|
||||
}
|
||||
}
|
||||
return other;
|
||||
}
|
||||
|
||||
/// Generate a random tensor of shape `shape`
|
||||
static Tensor random(List<int> shape) {
|
||||
Random r = Random();
|
||||
|
||||
int d1 = 0, d2 = 0;
|
||||
if (shape.length == 1) {
|
||||
d1 = shape[0];
|
||||
} else if (shape.length == 2) {
|
||||
d1 = shape[0];
|
||||
d2 = shape[1];
|
||||
} else if (shape.length == 3) {
|
||||
// d3 = shapes[2];
|
||||
}
|
||||
Tensor ret = Tensor(List.filled(d1, DelegatingList(List.filled(d2, 0.0))));
|
||||
|
||||
for (int i = 0; i < d1; ++i) {
|
||||
for (int j = 0; j < d2; ++j) {
|
||||
ret[i][j] = r.nextDouble();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Tensor stack(Tensor tensors, {int axis = 0}) {
|
||||
if (axis < -1 || axis > tensors.length - 1) {
|
||||
throw ArgumentError('Invalid axis value');
|
||||
}
|
||||
|
||||
int newAxisSize = tensors.length;
|
||||
for (var tensor in tensors) {
|
||||
newAxisSize *= tensor.length;
|
||||
}
|
||||
|
||||
Tensor result = Tensor([]);
|
||||
for (int i = 0; i < newAxisSize; i++) {
|
||||
int index = i;
|
||||
int currentAxisIndex = axis;
|
||||
List<int> currentAxisIndexes = List.filled(tensors.length, -1);
|
||||
int currentTensorIndex = 0;
|
||||
|
||||
while (currentAxisIndexes[currentTensorIndex] < tensors.length) {
|
||||
if (currentAxisIndexes[currentTensorIndex] == currentAxisIndex) {
|
||||
index = currentAxisIndexes[currentTensorIndex] +
|
||||
(index ~/ tensors.length);
|
||||
currentAxisIndexes[currentTensorIndex]++;
|
||||
}
|
||||
currentAxisIndex += (axis > 0 ? 1 : -1);
|
||||
currentTensorIndex =
|
||||
(currentAxisIndex < 0 || currentTensorIndex >= tensors.length)
|
||||
? 0
|
||||
: currentTensorIndex + 1;
|
||||
}
|
||||
|
||||
result.add(tensors[
|
||||
currentTensorIndex]); // Access tensors[currentTensorIndex] as a List<double> rather than using the index operator [] with it
|
||||
}
|
||||
|
||||
return Tensor(result);
|
||||
}
|
||||
|
||||
operator *(Tensor other) {
|
||||
return each((d, i, j) {
|
||||
return [i][j] * other[i][j];
|
||||
});
|
||||
}
|
||||
}
|
22
lib/src/test/splat/tensor_test.dart
Normal file
22
lib/src/test/splat/tensor_test.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'package:archimedes_test/src/splat/tensor.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('stack', () {
|
||||
test('A random tensor can be generated', () {
|
||||
Tensor generated = Tensor.random([2, 4]);
|
||||
expect(generated.length, equals(2));
|
||||
expect(generated[0].length, equals(4));
|
||||
});
|
||||
|
||||
test("A tensor can be stacked", () {
|
||||
Tensor x = Tensor(const DelegatingList([
|
||||
DelegatingList([0.3367, 0.1288, 0.2345]),
|
||||
DelegatingList([0.2303, -1.1229, -0.1863])
|
||||
]));
|
||||
|
||||
expect(Tensor.stack(x)[0], equals(x));
|
||||
});
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user